Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1361 lines
65 KiB

  1. ;/*
  2. ; * Microsoft Confidential
  3. ; * Copyright (C) Microsoft Corporation 1988 - 1991
  4. ; * All Rights Reserved.
  5. ; */
  6. ;************************************************************
  7. ;**
  8. ;** NAME: Support for HP PCL printers added to GRAPHICS.
  9. ;**
  10. ;** DESCRIPTION: I modified the procedures STORE_BOX, PRINT_BUFFER,
  11. ;** GET_SCREEN_INFO, DET_CUR_SCAN_LNE_LENGTH, and NEW_PRT_LINE
  12. ;** as follows.
  13. ;**
  14. ;** For STORE_BOX:
  15. ;** if data_type = data_row, then store printbox in print buffer
  16. ;** in row format - not column format.
  17. ;**
  18. ;** For PRINT_BUFFER:
  19. ;** if data_type = data_row, then print one byte at a time.
  20. ;**
  21. ;** For GET_SCREEN_INFO:
  22. ;** if data_type = data_row
  23. ;** nb_boxes_per_prt_buf = 8/box_height
  24. ;** if print_options = rotate
  25. ;** nb_scan_lines = screen_width
  26. ;** else
  27. ;** nb_scan_lines = screen_height
  28. ;** endif
  29. ;** endif
  30. ;**
  31. ;** For DET_CUR_SCAN_LNE_LENGTH:
  32. ;** if data_type = data_row
  33. ;** don't go down the columns to determine the scan_line_length
  34. ;** endif
  35. ;**
  36. ;** For NEW_PRT_LINE:
  37. ;** Altered it so send escape number sequence, COUNT or LOWCOUNT and
  38. ;** HIGHCOUNT, if they are specified before the new keyword DATA.
  39. ;**
  40. ;**
  41. ;** I added the the procedures END_PRT_LINE and GET_COUNT, which
  42. ;** are described below.
  43. ;**
  44. ;** END_PRT_LINE sends escape number sequence, COUNT or LOWCOUNT and
  45. ;** HIGHCOUNT, if they are specified after the new keyword DATA
  46. ;** in the GRAPHICS statement of the profile. It also sends a
  47. ;** CR & LF for IBM type printers if needed.
  48. ;**
  49. ;** GET_COUNT gets the number of bytes that are going to be sent to the
  50. ;** printer and converts the number to ASCII if DATA_TYPE = DATA_ROW.
  51. ;**
  52. ;** BUG NOTES: The following bug was fixed for the pre-release
  53. ;** version Q.01.02.
  54. ;**
  55. ;** BUG (mda003)
  56. ;** ------------
  57. ;**
  58. ;** NAME: GRAPHICS prints a CR & LF after each scan line unless it is
  59. ;** loaded twice.
  60. ;**
  61. ;** FILES & PROCEDURES AFFECTED: GRLOAD3.ASM - PARSE_GRAPHICS
  62. ;** GRCOMMON.ASM - END_PRT_LINE
  63. ;** GRSHAR.STR - N/A
  64. ;**
  65. ;** CAUSES: The local variables LOWCOUNT_FOUND, HIGHCOUNT_FOUND CR_FOUND and
  66. ;** LF_FOUND used for loading, were incorrectly being used as global
  67. ;** variables during printing.
  68. ;**
  69. ;** FIX: Created a new variable Printer_Needs_CR_LF in GRSHAR.STR, which
  70. ;** is used to determine in GRCOMMON.ASM if it's necessary to
  71. ;** manually send a CR & LF to the printer at print time. The
  72. ;** variable is set at load time in GRLOAD3.ASM, if the variables
  73. ;** Data_Found and Build_State are set.
  74. ;**
  75. ;** DOCUMENTATION NOTES: This version of GRCOMMON.ASM differs from the previous
  76. ;** version only in terms of documentation.
  77. ;**
  78. ;************************************************************
  79. PAGE ,132 ;AN000;
  80. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000;
  81. ;; DOS - GRAPHICS Command
  82. ;;
  83. ;; ;AN000;
  84. ;; File Name: GRCOMMON.ASM ;AN000;
  85. ;; ---------- ;AN000;
  86. ;; ;AN000;
  87. ;; Description: ;AN000;
  88. ;; ------------ ;AN000;
  89. ;; ;AN000;
  90. ;; This file contains the modules common to the Print Screen ;AN000;
  91. ;; process of GRAPHICS.COM. ;AN000;
  92. ;; This file is included by both set of Print modules. ;AN000;
  93. ;; ;AN000;
  94. ;; This file MUST BE COMPILED WITH EACH SET OF MODULES since, ;AN000;
  95. ;; one set is relocated in memory at installation time; all ;AN000;
  96. ;; references to the common procedures must be resolved from ;AN000;
  97. ;; within each set of print modules. ;AN000;
  98. ;; ;AN000;
  99. ;; The set of common modules is relocated in memory along with ;AN000;
  100. ;; the selected set of print modules. ;AN000;
  101. ;; ;AN000;
  102. ;; Documentation Reference: ;AN000;
  103. ;; ------------------------ ;AN000;
  104. ;; OASIS High Level Design ;AN000;
  105. ;; OASIS GRAPHICS I1 Overview ;AN000;
  106. ;; ;AN000;
  107. ;; Procedures Contained in This File: ;AN000;
  108. ;; ---------------------------------- ;AN000;
  109. ;; READ_DOT ;AN000;
  110. ;; LOC_MODE_PRT_INFO ;AN000;
  111. ;; STORE_BOX ;AN000;
  112. ;; PRINT_BUFFER ;AN000;
  113. ;; GET_SCREEN_INFO ;AN000;
  114. ;; SETUP_PRT ;AN000;
  115. ;; RESTORE_PRT ;AN000;
  116. ;; NEW_PRT_LINE ;AN000;
  117. ;; PRINT_BYTE ;AN000;
  118. ;; DET_CUR_SCAN_LNE_LENGTH ;AN000;
  119. ; \/ ~~mda(001) -----------------------------------------------------------------------
  120. ;; Added the following procedures to support printers with horizontal
  121. ;; printer heads, such as an HP PCL printers.
  122. ;; GET_COUNT
  123. ;; END_PRT_LINE
  124. ; /\ ~~mda(001) -----------------------------------------------------------------------
  125. ;; ;AN000;
  126. ;; Include Files Required: ;AN000;
  127. ;; ----------------------- ;AN000;
  128. ;; ;AN000;
  129. ;; External Procedure References: ;AN000;
  130. ;; ------------------------------ ;AN000;
  131. ;; FROM FILE GRCTRL.ASM: ;AN000;
  132. ;; PRT_SCR - Main module for printing the screen. ;AN000;
  133. ;; FROM FILE GRBWPRT.ASM: ;AN000;
  134. ;; PRT_BW_APA - Main module for printing on BW printer. ;AN000;
  135. ;; FROM FILE GRCOLPRT.ASM: ;AN000;
  136. ;; PRINT_COLOR - Main module for printing on COLOR printer. ;AN000;
  137. ;; ;AN000;
  138. ;; Linkage Instructions: ;AN000;
  139. ;; -------------------- ;AN000;
  140. ;; ;AN000;
  141. ;; This file is included by both GRBWPRT.ASM and GRCOLPRT.ASM and is ;AN000;
  142. ;; compiled with each of them. However, only one copy is made resident. ;AN000;
  143. ;; ;AN000;
  144. ;; Change History: ;AN000;
  145. ;; --------------- ;AN000;
  146. ;; ;AN000;
  147. ;; ;AN000;
  148. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;AN000;
  149. ;AN000;
  150. PAGE ;AN000;
  151. ;===============================================================================;AN000;
  152. ; ;AN000;
  153. ; LOC_MODE_PRT_INFO: LOCATE DISPLAYMODE PRINTER INFO. FOR THE CURRENT ;AN000;
  154. ; MODE ;AN000;
  155. ; ;AN000;
  156. ;-------------------------------------------------------------------------------;AN000;
  157. ; ;AN000;
  158. ; INPUT: BP = Offset of the shared data area ;AN000;
  159. ; CUR_MODE = Current video mode ;AN000;
  160. ; ;AN000;
  161. ; OUTPUT: CUR_MODE_PTR = Absolute Offset of the ;AN000;
  162. ; current DISPLAYMODE INFO record. ;AN000;
  163. ; ;AN000;
  164. ; ERROR_CODE = DISPLAYMODE_INFO_NOT_FOUND if not found. ;AN000;
  165. ; ;AN000;
  166. ; CALLED BY: PRINT_COLOR ;AN000;
  167. ; PRINT_BW_APA ;AN000;
  168. ; ;AN000;
  169. ; ;AN000;
  170. ;-------------------------------------------------------------------------------;AN000;
  171. ; ;AN000;
  172. ; DESCRIPTION: DISPLAYMODE_PTR is pointing to the first DISPLAYMODE ;AN000;
  173. ; INFO record within the Shared Data Area. ;AN000;
  174. ; ;AN000;
  175. ; This (chained) list of DISPLAYMODE records is scanned until the record ;AN000;
  176. ; for the current mode is found. ;AN000;
  177. ; ;AN000;
  178. ; Note: All pointers in the DISPLAYMODE records are relative to the beginning ;AN000;
  179. ; of the shared data area. Therefore, we must add the offset of the ;AN000;
  180. ; shared data area (in BP) in order to access the data these pointers ;AN000;
  181. ; are referencing. ;AN000;
  182. ; ;AN000;
  183. ; The CUR_MODE_PTR is relative to the segment and references the ;AN000;
  184. ; DISPLAYMODE record for the video mode currently set at print screen ;AN000;
  185. ; time. ;AN000;
  186. ; ;AN000;
  187. ; LOGIC: ;AN000;
  188. ; ;AN000;
  189. ; FOUND := FALSE ;AN000;
  190. ; DO UNTIL FOUND OR END_OF_LIST ;AN000;
  191. ; Get a display mode information record ;AN000;
  192. ; IF record.DISP_MODE = CUR_MODE ;AN000;
  193. ; THEN FOUND := TRUE ;AN000;
  194. ; ELSE ;AN000;
  195. ; CUR_MODE_PTR := record.NEXT_DISP_MODE ;AN000;
  196. ; ;AN000;
  197. ; ;AN000;
  198. ;AN000;
  199. LOC_MODE_PRT_INFO PROC NEAR ;AN000;
  200. PUSH BX ;AN000;
  201. PUSH CX ;AN000;
  202. PUSH DX ;AN000;
  203. PUSH SI ;AN000;
  204. ;AN000;
  205. MOV BX,DS:[BP].DISPLAYMODE_PTR ; [BX] := Current DISPLAYMODE ;AN000;
  206. ADD BX,BP ; record ;AN000;
  207. MOV DL,CUR_MODE ; DL := Current mode ;AN000;
  208. ;AN000;
  209. SCAN_1_DISPLAYMODE_RECORD: ;AN000;
  210. MOV SI,[BX].DISP_MODE_LIST_PTR ; [SI] : First mode covered ;AN000;
  211. ADD SI,BP ; by this DISPLAYMODE record ;AN000;
  212. MOV CL,[BX].NUM_DISP_MODE ; Scan each mode in the list ;AN000;
  213. XOR CH,CH ;AN000;
  214. SCAN_LIST_OF_MODES: ;AN000;
  215. CMP CS:[SI],DL ; FOUND ? ;AN000;
  216. JE FOUND ;AN000;
  217. INC SI ; NO, get next mode in ;AN000;
  218. LOOP SCAN_LIST_OF_MODES ; DISPLAYMODE record ;AN000;
  219. ;AN000;
  220. CMP [BX].NEXT_DISP_MODE,-1 ; END OF DISPLAYMODE LIST ? ;AN000;
  221. JE NOT_FOUND ; Yes, this mode not supported ;AN000;
  222. NEXT_RECORD: ; No, ;AN000;
  223. MOV BX,[BX].NEXT_DISP_MODE ; [BX] := Next record ;AN000;
  224. ADD BX,BP ; ;AN000;
  225. JMP SHORT SCAN_1_DISPLAYMODE_RECORD ;AN000;
  226. ;AN000;
  227. FOUND: ; Found: ;AN000;
  228. MOV CUR_MODE_PTR,BX ; Update pointer to current ;AN000;
  229. JMP SHORT LOC_MODE_PRT_INFO_END ; DISPLAYMODE record. ;AN000;
  230. ;AN000;
  231. NOT_FOUND: ; Not found: ;AN000;
  232. MOV ERROR_CODE,DISPLAYMODE_INFO_NOT_FOUND ; Return error condition ;AN000;
  233. ;AN000;
  234. LOC_MODE_PRT_INFO_END: ;AN000;
  235. POP SI ;AN000;
  236. POP DX ;AN000;
  237. POP CX ;AN000;
  238. POP BX ;AN000;
  239. RET ;AN000;
  240. LOC_MODE_PRT_INFO ENDP ;AN000;
  241. PAGE ;AN000;
  242. ;===============================================================================;AN000;
  243. ; ;AN000;
  244. ; STORE_BOX : STORE ONE BOX IN THE PRINT BUFFER. ;AN000;
  245. ; ;AN000;
  246. ;-------------------------------------------------------------------------------;AN000;
  247. ; ;AN000;
  248. ; INPUT: SI = OFFSET OF THE BOX TO BE PRINTED ;AN000;
  249. ; BOX_W = BOX WIDTH IN BITS ;AN000;
  250. ; BOX_H = BOX HEIGHT IN BITS ;AN000;
  251. ; ;AN000;
  252. ; OUTPUT: PRT_BUF = THE PRINT BUFFER ;AN000;
  253. ; ;AN000;
  254. ;-------------------------------------------------------------------------------;AN000;
  255. ; ;AN000;
  256. ; DESCRIPTION: The print buffer is first shifted left in order to make ;AN000;
  257. ; room for the new box (Note: the MSB's are lost; they are assumed to ;AN000;
  258. ; have been printed), then the box is inserted in the low-order bits of ;AN000;
  259. ; the printer buffer. ;AN000;
  260. ; ;AN000;
  261. PAGE ;AN000;
  262. ; EXAMPLE ;AN000;
  263. ; ------- ;AN000;
  264. ; BEFORE: AFTER: ;AN000;
  265. ; ;AN000;
  266. ; BOX: 0 0 0 ;AN000;
  267. ; 0 0 0 ;AN000;
  268. ; 0 0 0 ;AN000;
  269. ; 0 0 0 ;AN000;
  270. ; 0 0 0 ;AN000;
  271. ; 0 0 0 ;AN000;
  272. ; b1 b2 b3 ;AN000;
  273. ; b4 b5 b6 ;AN000;
  274. ; ;AN000;
  275. ; PRT_BUF: byte1 byte2 byte3 PRT_BUF: byte1 byte2 byte3 ;AN000;
  276. ; 0 1 0 1 1 1 ;AN000;
  277. ; 1 0 1 1 1 1 ;AN000;
  278. ; 1 1 1 1 1 1 ;AN000;
  279. ; 1 1 1 1 1 1 ;AN000;
  280. ; 1 1 1 1 1 1 ;AN000;
  281. ; 1 1 1 1 1 1 ;AN000;
  282. ; 1 1 1 b1 b2 b3 ;AN000;
  283. ; LSB --> 1 1 1 b4 b5 b6 ;AN000;
  284. ; ;AN000;
  285. ; ;AN000;
  286. ; LOGIC: ;AN000;
  287. ; ;AN000;
  288. ; FOR each byte of the buffer (BOX_W) ;AN000;
  289. ; BEGIN ;AN000;
  290. ; Make room for the box to be inserted ;AN000;
  291. ; Insert the box ;AN000;
  292. ; END ;AN000;
  293. ; ;AN000;
  294. STORE_BOX PROC NEAR ;AN000;
  295. PUSH BX ;AN000;
  296. PUSH CX ;AN000;
  297. PUSH DI ;AN000;
  298. ;AN000;
  299. MOV DI,OFFSET PRT_BUF ; DI := Offset of the Print buffer ;AN000;
  300. XOR BX,BX ; BX := Byte index number ;AN000;
  301. ; \/ ~~mda(001) -----------------------------------------------------------------------
  302. ; Added the following modification to support printers with
  303. ; vertical print heads, such as HP PCL printers. The code
  304. ; as is does not work for these printers because the data
  305. ; is being stored in the print buffer with the assumption
  306. ; that the print head is vertical.
  307. ;
  308. .IF <DS:[BP].DATA_TYPE EQ DATA_ROW>
  309. PUSH AX ;
  310. PUSH DX ;
  311. PUSH BP ;
  312. MOV CL,BOX_W ; Make room for the bits to be inserted.
  313. SHL BYTE PTR [BX][DI],CL ;
  314. MOV CL,DS:[BP].ROW_TO_EXTRACT ; CL determines which row we're extracting
  315. XOR BP,BP ; Point to first column.
  316. XOR DX,DX ; Clear counter
  317. XOR AX,AX ; Clear register
  318. ;
  319. EXTRACT_NEXT_BIT: ;
  320. ;
  321. SHL AH,1 ; Make room for next bit
  322. MOV AL,DS:[SI][BP] ; Read column
  323. SHR AL,CL ; Get bit from row we're extracting
  324. AND AL,1 ; Isolate bit we got from row we're extracting
  325. OR AH,AL ; Place it in AH
  326. INC BP ; Advance to next column
  327. INC DL ; Inc. counter
  328. CMP DL,BOX_W ; Check if have more bits to extract from the row
  329. JL EXTRACT_NEXT_BIT; We do
  330. OR DS:[DI][BX],AH ; We don't so place the row we extracted in the
  331. ; print buffer.
  332. POP BP ;
  333. POP DX ;
  334. POP AX ;
  335. .ELSE ;
  336. ; /\ ~~mda(001) -----------------------------------------------------------------------
  337. ;AN000;
  338. MOV CL,BOX_H ; CL := Number of BITS to be shifted ;AN000;
  339. ; FOR each column (byte) of the box to be stored in the buffer: ;AN000;
  340. STORE_1_BYTE: ;AN000;
  341. SHL BYTE PTR [BX][DI],CL ; Make room for the bits to be inserted ;AN000;
  342. MOV CH,[BX][SI] ; CH := column of the box to be inserted;AN000;
  343. OR [BX][DI],CH ; Insert the box column in the buffer ;AN000;
  344. INC BL ; Get next column (byte) of the box ;AN000;
  345. CMP BL,BOX_W ; All columns (bytes) of box stored ? ;AN000;
  346. JL STORE_1_BYTE ; No, store next one. ;AN000;
  347. .ENDIF ; ~~mda(001) Close the IF stmt ;AN000;
  348. STORE_BOX_END: ;AN000;
  349. POP DI ;AN000;
  350. POP CX ;AN000;
  351. POP BX ;AN000;
  352. RET ;AN000;
  353. STORE_BOX ENDP ;AN000;
  354. PAGE ;AN000;
  355. ;===============================================================================;AN000;
  356. ; ;AN000;
  357. ; PRINT_BUFFER : PRINT THE BUFFER ;AN000;
  358. ; ;AN000;
  359. ;-------------------------------------------------------------------------------;AN000;
  360. ; ;AN000;
  361. ; INPUT: PRT_BUF = BYTES TO BE PRINTED ;AN000;
  362. ; BOW_W = BOX WIDTH ;AN000;
  363. ; ;AN000;
  364. ; OUTPUT: PRINTER ;AN000;
  365. ; ;AN000;
  366. ;-------------------------------------------------------------------------------;AN000;
  367. ; ;AN000;
  368. ; DESCRIPTION: Prints BOX_W bytes. ;AN000;
  369. ; ;AN000;
  370. ; LOGIC: ;AN000;
  371. ; ;AN000;
  372. ; DO for each column in one pattern ;AN000;
  373. ; BEGIN ;AN000;
  374. ; Print one byte from the buffer ;AN000;
  375. ; END ;AN000;
  376. ; ;AN000;
  377. PRINT_BUFFER PROC NEAR ;AN000;
  378. PUSH AX ;AN000;
  379. PUSH BX ;AN000;
  380. PUSH CX ;AN000;
  381. ;AN000;
  382. MOV BX,OFFSET PRT_BUF ;AN000;
  383. ; \/ ~~mda(001) -----------------------------------------------------------------------
  384. ; If DATA_TYPE = DATA_ROW then the most we store in the print
  385. ; buffer at one time is one byte.
  386. .IF <DS:[BP].DATA_TYPE EQ DATA_ROW> ;
  387. MOV AL,[BX] ; Print one byte
  388. CALL PRINT_BYTE ;
  389. JC PRINT_BUFFER_END ; If printer error, quit the loop
  390. .ELSE
  391. ; /\ ~~mda(001) -----------------------------------------------------------------------
  392. XOR CX,CX ;AN000;
  393. MOV CL,BOX_W ;AN000;
  394. PRINT_1_BUF_COLUMN: ;AN000;
  395. MOV AL,[BX] ; Print one byte ;AN000;
  396. CALL PRINT_BYTE ;AN000;
  397. JC PRINT_BUFFER_END; If printer error, quit the loop ;AN000;
  398. INC BX ; Get next byte ;AN000;
  399. LOOP PRINT_1_BUF_COLUMN ;AN000;
  400. .ENDIF ;~~mda(001) close IF stmt
  401. PRINT_BUFFER_END: ;AN000;
  402. POP CX ;AN000;
  403. POP BX ;AN000;
  404. POP AX ;AN000;
  405. RET ;AN000;
  406. PRINT_BUFFER ENDP ;AN000;
  407. PAGE ;AN000;
  408. ;===============================================================================;AN000;
  409. ; ;AN000;
  410. ; GET_SCREEN_INFO : GET INFORMATION ABOUT HOW TO READ THE SCREEN. ;AN000;
  411. ; ;AN000;
  412. ;-------------------------------------------------------------------------------;AN000;
  413. ; ;AN000;
  414. ; INPUT: SCREEN_HEIGHT = Number of pixel rows on the screen ;AN000;
  415. ; SCREEN_WIDTH = Number of pixel columns on screen ;AN000;
  416. ; CUR_MODE_PTR = Offset of the current DISPLAYMODE info rec. ;AN000;
  417. ; ;AN000;
  418. ; OUTPUT: PRINTER ;AN000;
  419. ; SCAN_LINE_MAX_LENGTH = Maximum length of Screen scan line. ;AN000;
  420. ; NB_SCAN_LINES = Number of SCAN LINES on the screen ;AN000;
  421. ; CUR_ROW,CUR_COLUMN = Coordinates of the first pixel to be ;AN000;
  422. ; read on the screen ;AN000;
  423. ; NB_BOXES_PER_PRT_BUF = Number of boxes fitting in the Print ;AN000;
  424. ; buffer ;AN000;
  425. ; ;AN000;
  426. ; CALLED BY: PRINT_COLOR ;AN000;
  427. ; PRT_BW_APA ;AN000;
  428. ; ;AN000;
  429. ;-------------------------------------------------------------------------------;AN000;
  430. ; ;AN000;
  431. ; DESCRIPTION: ;AN000;
  432. ; ;AN000;
  433. ; 1) Determine where to start reading the screen. ;AN000;
  434. ; For non-rotated printing, it should start with the top-left ;AN000;
  435. ; corner pixel. ;AN000;
  436. ; For rotated printing, it should start with the low-left corner ;AN000;
  437. ; pixel. ;AN000;
  438. ; ;AN000;
  439. ; 2) Determine the length of a scan line. ;AN000;
  440. ; For non-rotated printing, it is the WIDTH of the screen. ;AN000;
  441. ; For rotated printing, it is the HEIGHT of the screen. ;AN000;
  442. ; ;AN000;
  443. ; 3) Determine the number of scan lines on the screen. ;AN000;
  444. ; For non-rotated printing, it is the HEIGHT of the screen divided ;AN000;
  445. ; by the number of boxes fitting in the print buffer. ;AN000;
  446. ; For rotated printing, it is the WIDTH of the screen divided by ;AN000;
  447. ; the number of boxes fitting in the print buffer. ;AN000;
  448. ; ;AN000;
  449. ; LOGIC: ;AN000;
  450. ; ;AN000;
  451. ; CUR_COLUMN := 0 ;AN000;
  452. ; IF printing is sideways ;AN000;
  453. ; THEN ;AN000;
  454. ; CUR_ROW := SCREEN_HEIGHT - 1 ; Low-left pixel ;AN000;
  455. ; SCAN_LINE_MAX_LENGTH := SCREEN_HEIGHT ;AN000;
  456. ; NB_SCAN_LINES := SCREEN_WIDTH / NB_BOXES_PER_PRT_BUF ;AN000;
  457. ; ELSE ;AN000;
  458. ; CUR_ROW := 0 ; Top-left pixel ;AN000;
  459. ; SCAN_LINE_MAX_LENGTH := SCREEN_WIDTH ;AN000;
  460. ; NB_SCAN_LINES := SCREEN_HEIGHT / NB_BOXES_PER_PRT_BUF ;AN000;
  461. ; ;AN000;
  462. ; ;AN000;
  463. GET_SCREEN_INFO PROC NEAR ;AN000;
  464. PUSH AX ;AN000;
  465. PUSH BX ; Used for DIV ;AN000;
  466. PUSH DX ; Used for DIV ;AN000;
  467. ;AN000;
  468. MOV BX,CUR_MODE_PTR ; BX := Offset DISPLAYMODE info record ;AN000;
  469. ;-------------------------------------------------------------------------------;AN000;
  470. ; ;AN000;
  471. ; Calculate how many printer boxes fit in the print buffer: ;AN000;
  472. ; ;AN000;
  473. ;-------------------------------------------------------------------------------;AN000;
  474. ; \/ ~~mda(001) -----------------------------------------------------------------------
  475. ; The NB_BOXES_PER_PRT_BUF depends on if the printer head is
  476. ; vertical, as in IBM's case, or if it's horizontal, as in
  477. ; HP's case. If DATA_TYPE is DATA_COL, then we have a vertical
  478. ; print head. If DATA_TYPE is DATA_ROW, then we have a
  479. ; horizontal print head.
  480. .IF <DS:[BP].DATA_TYPE EQ DATA_ROW> ; Print head is horizontal
  481. MOV AX,8 ; Num := 8 bits / Box width
  482. MOV DL,[BX].BOX_WIDTH ;
  483. DIV DL ;
  484. MOV NB_BOXES_PER_PRT_BUF,AL ;
  485. .ELSE ;
  486. ; /\ ~~mda(001) -----------------------------------------------------------------------
  487. MOV AX,8 ; Num := 8 bits / Box heigth ;AN000;
  488. MOV DL,[BX].BOX_HEIGHT ;AN000;
  489. DIV DL ;AN000;
  490. MOV NB_BOXES_PER_PRT_BUF,AL ;AN000;
  491. .ENDIF ; ~~mda(001) Close IF stmt.
  492. ;-------------------------------------------------------------------------------;AN000;
  493. ; ;AN000;
  494. ; Determine where to start reading the screen: ;AN000;
  495. ; ;AN000;
  496. ;-------------------------------------------------------------------------------;AN000;
  497. MOV CUR_COLUMN,0 ; Reading always start from left of scr ;AN000;
  498. .IF <[BX].PRINT_OPTIONS EQ ROTATE> ;AN000;
  499. .THEN ;AN000;
  500. ;-------------------------------------------------------------------------------;AN000;
  501. ; ;AN000;
  502. ; Printing is sideways; screen must be read starting in low-left corner. ;AN000;
  503. ; ;AN000;
  504. ;-------------------------------------------------------------------------------;AN000;
  505. MOV AX,SCREEN_HEIGHT ;AN000;
  506. MOV SCAN_LINE_MAX_LENGTH,AX ; Scan line length := screen height ;AN000;
  507. DEC AX ;AN000;
  508. MOV CUR_ROW,AX ; First row := screen height - 1 ;AN000;
  509. ;AN000;
  510. ;-------Calculate the number of scan lines: ;AN000;
  511. ; \/ ~~mda(001) -----------------------------------------------------------------------
  512. ; The NB_SCAN_LINES depends on if the printer head is
  513. ; vertical, as in IBM's case, or if it's horizontal, as in
  514. ; HP's case. If the printer head is horizontal, then we can't
  515. ; make use of the concept of scan lines. However, we can still
  516. ; use the symbol NB_SCAN_LINES by just stuffing into it the
  517. ; screen width.
  518. ;
  519. .IF <DS:[BP].DATA_TYPE EQ DATA_ROW> ; Print head is horizontal
  520. MOV AX,SCREEN_WIDTH ; DX AX = Screen width
  521. CWD ;
  522. MOV NB_SCAN_LINES,AX;
  523. .ELSE
  524. ; /\ ~~mda(001) -----------------------------------------------------------------------
  525. MOV AX,SCREEN_WIDTH ; DX AX = Screen width ;AN000;
  526. CWD ; ;AN000;
  527. XOR BX,BX ; BX = Number of boxes per print buf ;AN000;
  528. MOV BL,NB_BOXES_PER_PRT_BUF ; ;AN000;
  529. DIV BX ; Screen width / number boxes per buff ;AN000;
  530. MOV NB_SCAN_LINES,AX ; Number of scan lines := result ;AN000;
  531. .ENDIF ; ~~mda(001) Close IF stmt.
  532. .ELSE ;AN000;
  533. ;-------------------------------------------------------------------------------;AN000;
  534. ; ;AN000;
  535. ; Printing is not sideways; screen must be read starting in top-left corner ;AN000;
  536. ; ;AN000;
  537. ;-------------------------------------------------------------------------------;AN000;
  538. MOV AX,SCREEN_WIDTH ;AN000;
  539. MOV SCAN_LINE_MAX_LENGTH,AX ; Scan line length := screen width ;AN000;
  540. MOV CUR_ROW,0 ; First row := 0 ;AN000;
  541. ;AN000;
  542. ;-------Calculate the number of scan lines: ;AN000;
  543. ; \/ ~~mda(001) -----------------------------------------------------------------------
  544. ; The NB_SCAN_LINES depends on if the printer head is
  545. ; vertical, as in IBM's case, or if it's horizontal, as in
  546. ; HP's case. If the printer head is horizontal, then we can't
  547. ; make use of the concept of scan lines. However, we can still
  548. ; use the symbol NB_SCAN_LINES by just stuffing into it the
  549. ; screen height.
  550. ;
  551. .IF <DS:[BP].DATA_TYPE EQ DATA_ROW> ; Print head is vertical
  552. MOV AX,SCREEN_HEIGHT; DX AX = Screen height
  553. CWD ;
  554. MOV NB_SCAN_LINES,AX;
  555. .ELSE
  556. ; /\ ~~mda(001) -----------------------------------------------------------------------
  557. MOV AX,SCREEN_HEIGHT ; DX AX = Screen height ;AN000;
  558. CWD ; ;AN000;
  559. XOR BX,BX ; BX = Number of boxes per print buff ;AN000;
  560. MOV BL,NB_BOXES_PER_PRT_BUF ; ;AN000;
  561. DIV BX ; Screen height/number boxes per buff. ;AN000;
  562. MOV NB_SCAN_LINES,AX ; Number of scan lines := result ;AN000;
  563. .ENDIF ; ~~mda(001) Close IF stmt.
  564. .ENDIF ;AN000;
  565. POP DX ;AN000;
  566. POP BX ;AN000;
  567. POP AX ;AN000;
  568. RET ;AN000;
  569. GET_SCREEN_INFO ENDP ;AN000;
  570. PAGE ;AN000;
  571. ;===============================================================================;AN000;
  572. ; ;AN000;
  573. ; DET_CUR_SCAN_LNE_LENGTH : Determine where is the last non-blank "scan line ;AN000;
  574. ; column" on the current scan line. ;AN000;
  575. ; ;AN000;
  576. ;-------------------------------------------------------------------------------;AN000;
  577. ; ;AN000;
  578. ; INPUT: CUR_ROW, ;AN000;
  579. ; CUR_COLUMN = Coordinates of the top pixel of the current ;AN000;
  580. ; scan line. ;AN000;
  581. ; XLT_TAB = Color translation table ;AN000;
  582. ; ;AN000;
  583. ; OUTPUT: CUR_SCAN_LNE_LENGTH = Number of "columns" of pixels from the ;AN000;
  584. ; beginning of the scan line up to ;AN000;
  585. ; the last non-blank pixel. ;AN000;
  586. ; ;AN000;
  587. ; DATA SCREEN_WIDTH, ;AN000;
  588. ; REFERENCED: SCREEN_HEIGHT = Dimensions of the screen in pels ;AN000;
  589. ; SCAN_LINE_MAX_LENGTH= Maximum length of the scan line ;AN000;
  590. ; ROTATE_SW = ON if printing is sideways ;AN000;
  591. ; ;AN000;
  592. ;-------------------------------------------------------------------------------;AN000;
  593. ; ;AN000;
  594. ; DESCRIPTION: Determine where is the last non-blank "column" by reading ;AN000;
  595. ; the scan line backwards, one column at a time. ;AN000;
  596. ; ;AN000;
  597. ; ;AN000;
  598. ; LOGIC: ;AN000;
  599. ; ;AN000;
  600. ; ; Obtain coordinates for the top pixel of the last column on the current ;AN000;
  601. ; ; scan line: ;AN000;
  602. ; IF printing is sideways ;AN000;
  603. ; THEN ;AN000;
  604. ; CUR_ROW := 0 ;AN000;
  605. ; ELSE ;AN000;
  606. ; CUR_COLUMN := SCREEN_WIDTH - 1 ;AN000;
  607. ; ;AN000;
  608. ; CUR_SCAN_LNE_LENGTH := SCAN_LINE_MAX_LENGTH ;AN000;
  609. ; ; Read a column of pixels on the scan line until a non-blank is found: ;AN000;
  610. ; For each column on the screen ;AN000;
  611. ; CALL FILL_BUFF ;AN000;
  612. ; ; Check if PRT_BUF is empty ;AN000;
  613. ; IF buffer is empty ;AN000;
  614. ; THEN DEC CUR_SCAN_LNE_LENGTH ;AN000;
  615. ; ; Get next column ;AN000;
  616. ; IF printing sideways THEN DEC CUR_ROW ;AN000;
  617. ; ELSE DEC CUR_COLUMN ;AN000;
  618. ; ELSE quit the loop ;AN000;
  619. ; ;AN000;
  620. DET_CUR_SCAN_LNE_LENGTH PROC NEAR ;AN000;
  621. PUSH AX ;AN000;
  622. PUSH BX ;AN000;
  623. PUSH CX ;AN000;
  624. PUSH DX ;AN000;
  625. PUSH SI ;AN000;
  626. PUSH DI ;AN000;
  627. PUSH CUR_COLUMN ;AN000;
  628. PUSH CUR_ROW ;AN000;
  629. ;AN000;
  630. MOV BX,OFFSET XLT_TAB ; BX := Offset of XLT_TAB ;AN000;
  631. ;-------------------------------------------------------------------------------;AN000;
  632. ; ;AN000;
  633. ; Obtain coordinates of the top pixel for the last column of the current ;AN000;
  634. ; scan line: ;AN000;
  635. ; ;AN000;
  636. ;-------------------------------------------------------------------------------;AN000;
  637. .IF <ROTATE_SW EQ ON> ; If printing sideways ;AN000;
  638. .THEN ; then, ;AN000;
  639. MOV CUR_ROW,0 ; CUR_ROW := 0 ;AN000;
  640. .ELSE ; else, ;AN000;
  641. MOV CX,SCREEN_WIDTH ; CUR_COLUMN := SCREEN_WIDTH - 1 ;AN000;
  642. DEC CX ; ;AN000;
  643. MOV CUR_COLUMN,CX ; ;AN000;
  644. .ENDIF ;AN000;
  645. ;-------------------------------------------------------------------------------;AN000;
  646. ; ;AN000;
  647. ; Read the scan line backwards "column" by "column" until a non-blank is found: ;AN000;
  648. ; ;AN000;
  649. ;-------------------------------------------------------------------------------;AN000;
  650. MOV CX,SCAN_LINE_MAX_LENGTH ; CX := current length ;AN000;
  651. ; ;AN000;
  652. ;-------For each "column" ;AN000;
  653. CHECK_1_COLUMN: ;AN000;
  654. MOV SI,CUR_ROW ; Save coordinates of the column ;AN000;
  655. MOV DI,CUR_COLUMN ; in SI, DI ;AN000;
  656. XOR DL,DL ; DL := Number of pixels verified in ;AN000;
  657. ; one "column" ;AN000;
  658. ; ;AN000;
  659. ;-------For each pixel within that "column" ;AN000;
  660. CHECK_1_PIXEL: ;AN000;
  661. CALL READ_DOT ; AL := Index into translation table ;AN000;
  662. XLAT XLT_TAB ; AL := Band mask or Intensity ;AN000;
  663. ;AN000;
  664. ;-------Check if pixel will map to an empty box: ;AN000;
  665. .IF <DS:[BP].PRINTER_TYPE EQ BLACK_WHITE> ; If BLACK AND WHITE printer ;AN000;
  666. .THEN ; then, check for intensity of white ;AN000;
  667. CMP AL,WHITE_INT ; If curent pixel not blank ;AN000;
  668. JNE DET_LENGTH_END ; THEN, LEAVE THE LOOP ;AN000;
  669. .ELSE ; else, COLOR printer ;AN000;
  670. OR AL,AL ; IF Band mask not blank ;AN000;
  671. JNZ DET_LENGTH_END ; THEN, LEAVE THE LOOP ;AN000;
  672. .ENDIF ;AN000;
  673. ;AN000;
  674. ; \/ ~~mda(001) -----------------------------------------------------------------------
  675. ; Only if DATA_TYPE is DATA_COL do we have "columns",
  676. ; so skip this section otherwise.
  677. .IF <DS:[BP].DATA_TYPE EQ DATA_COL> ; Print head is vertical
  678. ; /\ ~~mda(001) -----------------------------------------------------------------------
  679. ;-------All pixels so far on this "column" are blank, get next pixel: ;AN000;
  680. .IF <ROTATE_SW EQ ON> ; If printing sideways ;AN000;
  681. .THEN ; ;AN000;
  682. INC CUR_COLUMN ; then, increment column number ;AN000;
  683. .ELSE ; ;AN000;
  684. INC CUR_ROW ; else, increment row number ;AN000;
  685. .ENDIF ; ;AN000;
  686. INC DL ; One more pixel checked ;AN000;
  687. CMP DL,NB_BOXES_PER_PRT_BUF ; All pixels for that column done ? ;AN000;
  688. JL CHECK_1_PIXEL ; No, check next one. ;AN000;
  689. .ENDIF ;~~mda(001) Close IF stmt.
  690. ;AN000;
  691. ;-------Nothing to print for this column, get next column ;AN000;
  692. .IF <ROTATE_SW EQ ON> ; If printing sideways ;AN000;
  693. .THEN ; then, ;AN000;
  694. MOV CUR_COLUMN,DI ; Restore column number ;AN000;
  695. INC CUR_ROW ; Get next row ;AN000;
  696. .ELSE ; else, ;AN000;
  697. MOV CUR_ROW,SI ; Restore row number ;AN000;
  698. DEC CUR_COLUMN ; Get next column ;AN000;
  699. .ENDIF ; ;AN000;
  700. LOOP CHECK_1_COLUMN ; CX (length) := CX - 1 ;AN000;
  701. ;AN000;
  702. DET_LENGTH_END: ;AN000;
  703. MOV CUR_SCAN_LNE_LENGTH,CX ; Get current length ;AN000;
  704. ;AN000;
  705. POP CUR_ROW ;AN000;
  706. POP CUR_COLUMN ;AN000;
  707. POP DI ;AN000;
  708. POP SI ;AN000;
  709. POP DX ;AN000;
  710. POP CX ;AN000;
  711. POP BX ;AN000;
  712. POP AX ;AN000;
  713. RET ;AN000;
  714. DET_CUR_SCAN_LNE_LENGTH ENDP ;AN000;
  715. PAGE ;AN000;
  716. ;===============================================================================;AN000;
  717. ; ;AN000;
  718. ; SETUP_PRT : SET UP THE PRINTER FOR PRINTING IN GRAPHIC MODE ;AN000;
  719. ; ;AN000;
  720. ;-------------------------------------------------------------------------------;AN000;
  721. ; ;AN000;
  722. ; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000;
  723. ; record for the current mode ;AN000;
  724. ; ;AN000;
  725. ; OUTPUT: PRINTER ;AN000;
  726. ; ;AN000;
  727. ; CALLED BY: PRINT_COLOR ;AN000;
  728. ; PRT_BW_APA ;AN000;
  729. ; ;AN000;
  730. ;-------------------------------------------------------------------------------;AN000;
  731. ; ;AN000;
  732. ; DESCRIPTION: Extract the SETUP escape sequence from the DISPLAYMODE ;AN000;
  733. ; information record; Send this escape sequence to the printer. ;AN000;
  734. ; ;AN000;
  735. ; LOGIC: ;AN000;
  736. ; ;AN000;
  737. ; Number of bytes to print := CUR_MODE_PTR.NUM_SETUP_ESC ;AN000;
  738. ; ;AN000;
  739. ; Get the escape sequence: ;AN000;
  740. ; SI := CUR_MODE_PTR.SETUP_ESC_PTR ;AN000;
  741. ; ;AN000;
  742. ; FOR each byte to be printed ;AN000;
  743. ; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000;
  744. ; INC SI ; Get the next byte ;AN000;
  745. ; ;AN000;
  746. SETUP_PRT PROC NEAR ;AN000;
  747. PUSH AX ;AN000;
  748. PUSH BX ;AN000;
  749. PUSH CX ;AN000;
  750. ;AN000;
  751. MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000;
  752. ;AN000;
  753. XOR CX,CX ; CX := Number of bytes to print ;AN000;
  754. MOV CL,[BX].NUM_SETUP_ESC ; ;AN000;
  755. .IF <CL G 0> ; If there is at least one ;AN000;
  756. .THEN ; byte to be printed: ;AN000;
  757. MOV BX,[BX].SETUP_ESC_PTR ; BX := Offset sequence to send ;AN000;
  758. ADD BX,BP ;AN000;
  759. ;AN000;
  760. SEND_1_SETUP_BYTE: ;AN000;
  761. MOV AL,[BX] ; AL := byte to print ;AN000;
  762. CALL PRINT_BYTE ; Send it to the printer ;AN000;
  763. JC SETUP_PRT_END ; If printer error, quit the loop ;AN000;
  764. INC BX ; Get next byte ;AN000;
  765. LOOP SEND_1_SETUP_BYTE ;AN000;
  766. .ENDIF ;AN000;
  767. SETUP_PRT_END: ;AN000;
  768. POP CX ;AN000;
  769. POP BX ;AN000;
  770. POP AX ;AN000;
  771. RET ;AN000;
  772. SETUP_PRT ENDP ;AN000;
  773. PAGE ;AN000;
  774. ;===============================================================================;AN000;
  775. ; ;AN000;
  776. ; RESTORE_PRT : RESTORE THE PRINTER TO ITS INITIAL STATUS ;AN000;
  777. ; ;AN000;
  778. ;-------------------------------------------------------------------------------;AN000;
  779. ; ;AN000;
  780. ; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000;
  781. ; record for the current mode ;AN000;
  782. ; ;AN000;
  783. ; OUTPUT: PRINTER ;AN000;
  784. ; ;AN000;
  785. ; CALLED BY: PRINT_COLOR ;AN000;
  786. ; PRT_BW_APA ;AN000;
  787. ;-------------------------------------------------------------------------------;AN000;
  788. ; ;AN000;
  789. ; DESCRIPTION: Extract the RESTORE escape sequence from the DISPLAYMODE ;AN000;
  790. ; information record; Send this escape sequence to the printer. ;AN000;
  791. ; ;AN000;
  792. ; LOGIC: ;AN000;
  793. ; ;AN000;
  794. ; Number of bytes to print := CUR_MODE_PTR.NUM_RESTORE_ESC ;AN000;
  795. ; ;AN000;
  796. ; Get the escape sequence: ;AN000;
  797. ; SI := CUR_MODE_PTR.RESTORE_ESC_PTR ;AN000;
  798. ; FOR each byte to be printed ;AN000;
  799. ; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000;
  800. ; INC SI ; Get the next byte ;AN000;
  801. ; ;AN000;
  802. RESTORE_PRT PROC NEAR ;AN000;
  803. PUSH AX ;AN000;
  804. PUSH BX ;AN000;
  805. PUSH CX ;AN000;
  806. ;AN000;
  807. MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000;
  808. ;AN000;
  809. XOR CX,CX ; CX := Number of bytes to print ;AN000;
  810. MOV CL,[BX].NUM_RESTORE_ESC ;AN000;
  811. .IF <CL G 0> ; If there is at least one ;AN000;
  812. .THEN ; byte to be printed: ;AN000;
  813. MOV BX,[BX].RESTORE_ESC_PTR ; BX := Offset sequence to send ;AN000;
  814. ADD BX,BP ;AN000;
  815. ;AN000;
  816. SEND_1_RESTORE_BYTE: ;AN000;
  817. MOV AL,[BX] ; AL := byte to print ;AN000;
  818. CALL PRINT_BYTE ; Send it to the printer ;AN000;
  819. JC RESTORE_PRT_END ; If printer error, quit the loop ;AN000;
  820. INC BX ; Get next byte ;AN000;
  821. LOOP SEND_1_RESTORE_BYTE ;AN000;
  822. .ENDIF ;AN000;
  823. RESTORE_PRT_END: ;AN000;
  824. POP CX ;AN000;
  825. POP BX ;AN000;
  826. POP AX ;AN000;
  827. RET ;AN000;
  828. RESTORE_PRT ENDP ;AN000;
  829. PAGE ;AN000;
  830. ;===============================================================================;AN000;
  831. ; ;AN000;
  832. ; NEW_PRT_LINE : INITIALIZE THE PRINTER FOR A GRAPHIC LINE ;AN000;
  833. ; ;AN000;
  834. ;-------------------------------------------------------------------------------;AN000;
  835. ; ;AN000;
  836. ; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information ;AN000;
  837. ; record for the current mode ;AN000;
  838. ; CUR_SCAN_LNE_LENGTH = Number of bytes to send to the printer. ;AN000;
  839. ; ;AN000;
  840. ; OUTPUT: PRINTER ;AN000;
  841. ; ;AN000;
  842. ; CALLED BY: PRINT_BAND ;AN000;
  843. ; PRT_BW_APA ;AN000;
  844. ; ;AN000;
  845. ;-------------------------------------------------------------------------------;AN000;
  846. ; ;AN000;
  847. ; DESCRIPTION: Extract the GRAPHICS escape sequence from the DISPLAYMODE ;AN000;
  848. ; information record; Send this escape sequence to the printer. ;AN000;
  849. ; Then, send the number of bytes that will follow. ;AN000;
  850. ; ;AN000;
  851. ; LOGIC: ;AN000;
  852. ; ;AN000;
  853. ; Number of bytes to print := CUR_MODE_PTR.NUM_GRAPHICS_ESC ;AN000;
  854. ; ;AN000;
  855. ; Get the escape sequence: ;AN000;
  856. ; Set up the 2 bytes containing the number of bytes to send in this sequence. ;AN000;
  857. ; SI := CUR_MODE_PTR.GRAPHICS_ESC_PTR ;AN000;
  858. ; ;AN000;
  859. ; FOR each byte to be printed ;AN000;
  860. ; PRINT_BYTE [SI] ; Send the byte to the printer ;AN000;
  861. ; INC SI ; Get the next byte ;AN000;
  862. ; ;AN000;
  863. ; Send the byte count ;AN000;
  864. ; ;AN000;
  865. ;AN000;
  866. NEW_PRT_LINE PROC NEAR ;AN000;
  867. PUSH AX ;AN000;
  868. PUSH BX ;AN000;
  869. PUSH CX ;AN000;
  870. PUSH DX ;AN000;
  871. PUSH DI ;AN000;
  872. ;AN000;
  873. MOV BX,CUR_MODE_PTR ; BX := Displaymode info record. ;AN000;
  874. ;AN000;
  875. ;-------------------------------------------------------------------------------;AN000;
  876. ; Set up the 2 bytes containing the number of bytes to send in the GRAPHICS seq.;AN000;
  877. ; NOTE: number of bytes to send is "CUR_SCAN_LNE_LENGTH * BOX_W" ;AN000;
  878. ;-------------------------------------------------------------------------------;AN000;
  879. MOV AL,BOX_W ; cur_scan_lne_length * ;AN000;
  880. CBW ; printer box width = nb bytes to send;AN000;
  881. MUL CUR_SCAN_LNE_LENGTH ; (result in DX AX) ;AN000;
  882. ;-------AX := Number of bytes to print ;AN000;
  883. ; \/ ~~mda(001) -----------------------------------------------------------------------
  884. ; Since we have added the key words DATA and COUNT to the
  885. ; list of allowable words for the GRAPHICS statement
  886. ; we have to take into consideration if the esc. sequence
  887. ; numbers come before of after the word DATA. Also we have
  888. ; to take into consideration if the printer is expecting
  889. ; to receive the COUNT in binary form or in ASCII form.
  890. ; Note this section of code replaces the section of code
  891. ; which follows it.
  892. MOV DI,[BX].GRAPHICS_ESC_PTR ; DI := offset seq. to send
  893. XOR CX,CX ; CX := Length of the escape seq
  894. MOV CL,[BX].NUM_GRAPHICS_ESC ; before the word DATA
  895. .WHILE <CX NE 0> ; Doing while loop just in case DATA is the
  896. ; first word after GRAPHICS. In that case
  897. ; skip this and send the actual data.
  898. MOV BL,BYTE PTR DS:[BP+DI] ; Get code.
  899. ;
  900. .SELECT ; Case statement
  901. .WHEN <BL EQ ESC_NUM_CODE> ; We have an esc. number
  902. PUSH AX ; Save count
  903. INC DI ; Point to esc. number
  904. MOV AL,DS:[BP+DI] ;
  905. CALL PRINT_BYTE ; Send esc. number
  906. JC NEW_PRT_LINE_ENDP_1 ; If printer error then quit
  907. ; the loop and restore registers
  908. INC DI ; Point to next tag
  909. POP AX ; Restore the count
  910. DEC CX ;
  911. .WHEN <BL EQ COUNT_CODE> ; Need to send count in ascii form
  912. PUSH AX ; Save count
  913. PUSH SI ;
  914. CALL GET_COUNT ; Get # bytes to send to printer
  915. PUSH CX ; Save counter for outside loop
  916. XOR CH,CH ;
  917. MOV CL,DS:[BP].NUM_BYTES_FOR_COUNT ;
  918. LEA SI,DS:[BP].COUNT ; Get ptr. to count
  919. SUB SI,CX ; Need to send MSB first
  920. INC SI ;
  921. CLD ;
  922. SEND_ASCII_COUNT: ;
  923. LODSB ;
  924. CALL PRINT_BYTE ; Print it
  925. JC NEW_PRT_LINE_ENDP_2 ; If printer error then quit
  926. ; the loop and restore registers
  927. LOOP SEND_ASCII_COUNT ;
  928. POP CX ; Restore outside loop counter
  929. ADD DI,2 ; Point to next tag
  930. POP SI ;
  931. POP AX ; Restore COUNT
  932. DEC CX ;
  933. .WHEN <BL EQ LOWCOUNT_CODE> ; Sending lowbyte of COUNT
  934. CALL PRINT_BYTE ; Print it
  935. JC NEW_PRT_LINE_ENDP ; If printer error then quit
  936. ADD DI,2 ; Point to next tag
  937. DEC CX ;
  938. .WHEN <BL EQ HIGHCOUNT_CODE> ; Sending highbyte of COUNT
  939. PUSH AX ; Save count
  940. CWD ;
  941. MOV BX,100h ;
  942. DIV BX ; Put highbyte in AL
  943. CALL PRINT_BYTE ; Print it
  944. JC NEW_PRT_LINE_ENDP_1 ; If printer error then quit
  945. ; the loop and restore registers
  946. ADD DI,2 ; Point to next tag
  947. ; the loop.
  948. POP AX ; Restore count
  949. DEC CX ;
  950. .ENDSELECT ;
  951. .ENDWHILE ;
  952. ADD DI,2 ; Skip over DATA tag and byte
  953. ; so pointing to correct place when
  954. ; get to END_PRT_LINE proc.
  955. ; /\ ~~mda(001) -----------------------------------------------------------------------
  956. ; \/ ~~mda(001) -----------------------------------------------------------------------
  957. ; The following piece of code is replaced by the above piece
  958. ; of code.
  959. ;
  960. ;;;; MOV DI,[BX].LOW_BYT_COUNT_PTR; DI := Offset of LOW byte of ;AN000;
  961. ;;;; ADD DI,BP ; byte count ;AN000;
  962. ;;;; MOV [DI],AL ; Store low byte ;AN000;
  963. ;;;; MOV DI,[BX].HGH_BYT_COUNT_PTR; DI := Offset of HIGH byte of ;AN000;
  964. ;;;; ADD DI,BP ; byte count ;AN000;
  965. ;;;; MOV [DI],AH ; Store high byte ;AN000;
  966. ;;;; ;AN000;
  967. ;;;;;-------------------------------------------------------------------------------;AN000;
  968. ;;;;; Send the GRAPHICS escape sequence to the printer: ;AN000;
  969. ;;;;;-------------------------------------------------------------------------------;AN000;
  970. ;;;; XOR CX,CX ; CX := Length of the escape seq;AN000;
  971. ;;;; MOV CL,[BX].NUM_GRAPHICS_ESC ;AN000;
  972. ;;;; MOV BX,[BX].GRAPHICS_ESC_PTR ; BX := Offset sequence to send ;AN000;
  973. ;;;; ADD BX,BP ;AN000;
  974. ;;;; ;AN000;
  975. ;;;;SEND_1_GRAPHICS_BYTE: ;AN000;
  976. ;;;; MOV AL,[BX] ; AL := byte to print ;AN000;
  977. ;;;; CALL PRINT_BYTE ; Send it to the printer ;AN000;
  978. ;;;; JC NEW_PRT_LINE_ENDP ; If printer error, quit the loop ;AN000;
  979. ;;;; INC BX ; Get next byte ;AN000;
  980. ;;;; LOOP SEND_1_GRAPHICS_BYTE ;AN000;
  981. ; /\ ~~mda(001) -----------------------------------------------------------------------
  982. JMP SHORT NEW_PRT_LINE_ENDP ; ~~mda(001) Restore registers
  983. JMP SHORT NEW_PRT_LINE_ENDP ;
  984. NEW_PRT_LINE_ENDP_2: ; ~~mda(001)
  985. POP SI
  986. NEW_PRT_LINE_ENDP_1: ; ~~mda(001)
  987. POP AX
  988. NEW_PRT_LINE_ENDP: ;AN000;
  989. POP DI ;AN000;
  990. POP DX ;AN000;
  991. POP CX ;AN000;
  992. POP BX ;AN000;
  993. POP AX ;AN000;
  994. RET ;AN000;
  995. NEW_PRT_LINE ENDP ;AN000;
  996. PAGE ;AN000;
  997. ; \/ ~~mda(001) -----------------------------------------------------------------------
  998. ; Since we have the keyword DATA, and we allow it to be anywhere
  999. ; on the GRAPHICS line, then it is possible to have an
  1000. ; esc. sequence to send to the printer after the data has been
  1001. ; sent. Therefore we need this new procedure.
  1002. ;===============================================================================
  1003. ;
  1004. ; END_PRT_LINE : SEND THE REST OF THE GRAPHICS LINE
  1005. ;
  1006. ;-------------------------------------------------------------------------------
  1007. ;
  1008. ; INPUT: CUR_MODE_PTR = Offset of the DISPLAYMODE information
  1009. ; record for the current mode
  1010. ; DI = Points to the section of the esc. seq that
  1011. ; comes after the keyword DATA.
  1012. ;
  1013. ; OUTPUT: PRINTER
  1014. ;
  1015. ; CALLED BY: PRT_BW_APA
  1016. ;
  1017. ;-------------------------------------------------------------------------------
  1018. ;
  1019. ; DESCRIPTION: Extract the GRAPHICS escape sequence that comes after the keyword
  1020. ; DATA from the DISPLAYMODE information record; Send this escape sequence to the
  1021. ; printer.
  1022. ;
  1023. ;
  1024. CR_FOUND DB ? ; So we know if a carriage return has been sent
  1025. LF_FOUND DB ? ; So we know if a line feed has been sent
  1026. END_PRT_LINE PROC NEAR
  1027. PUSH AX
  1028. PUSH BX
  1029. PUSH CX
  1030. PUSH DX
  1031. PUSH DI
  1032. MOV CR_FOUND,NO ; Initialize
  1033. MOV LF_FOUND,NO ;
  1034. MOV BX,CUR_MODE_PTR ; BX := Displaymode info record.
  1035. ;-------------------------------------------------------------------------------
  1036. ; Set up the 2 bytes containing the number of bytes to send in the GRAPHICS seq.
  1037. ; NOTE: number of bytes to send is "CUR_SCAN_LNE_LENGTH * BOX_W"
  1038. ;-------------------------------------------------------------------------------
  1039. MOV AL,BOX_W ; cur_scan_lne_length *
  1040. CBW ; printer box width = nb bytes to send
  1041. MUL CUR_SCAN_LNE_LENGTH ; (result in DX AX)
  1042. ;-------AX := Number of bytes to print
  1043. XOR CX,CX ; CX := Length of the escape seq
  1044. MOV CL,[BX].NUM_GRAPHICS_ESC_AFTER_DATA ;after the word DATA
  1045. .WHILE <CX NE 0> ; Doing a while loop just in case DATA is the
  1046. ; last word on the GRAPHICS line. In that case
  1047. ; skip this and send a CR or LF if needed.
  1048. MOV BL,BYTE PTR DS:[BP+DI] ; Get code.
  1049. .SELECT ; Case statement
  1050. .WHEN <BL EQ ESC_NUM_CODE> ; We have an esc. number
  1051. PUSH AX ; Save count
  1052. INC DI ; Point to esc. number
  1053. MOV AL,DS:[BP+DI] ;
  1054. .IF <AL EQ CR> ; Check if a CR is
  1055. MOV CR_FOUND,YES ; explicitly stated
  1056. .ENDIF
  1057. .IF <AL EQ LF> ; Check if a LF is
  1058. MOV LF_FOUND,YES ; explicitly stated
  1059. .ENDIF
  1060. CALL PRINT_BYTE ; Send esc. number
  1061. JC GOTO_END_PRT_LINE_ENDP_1; If printer error then quit
  1062. ; the loop and restore registers
  1063. INC DI ; Point to next tag
  1064. POP AX ; Restore the count
  1065. DEC CX ;
  1066. .WHEN <BL EQ COUNT_CODE> ; Need to send count in ascii form
  1067. PUSH AX ; Save count
  1068. PUSH SI ;
  1069. CALL GET_COUNT ; Get # of bytes to send to printer
  1070. PUSH CX ; Save counter for outside loop
  1071. XOR CH,CH ;
  1072. MOV CL,DS:[BP].NUM_BYTES_FOR_COUNT ;
  1073. LEA SI,DS:[BP].COUNT ; Get ptr. to count
  1074. SUB SI,CX ; Need to send MSB first
  1075. INC SI ;
  1076. CLD ;
  1077. SEND_THE_ASCII_COUNT: ;
  1078. LODSB ;
  1079. CALL PRINT_BYTE ; Print it
  1080. JC GOTO_END_PRT_LINE_ENDP_2 ; If printer error then quit
  1081. ; the loop and restore registers.
  1082. LOOP SEND_THE_ASCII_COUNT ;
  1083. POP CX ; Restore outside loop counter
  1084. ADD DI,2 ; Point to next tag
  1085. POP SI ;
  1086. POP AX ; Restore COUNT
  1087. DEC CX ;
  1088. .WHEN <BL EQ LOWCOUNT_CODE> ; Sending lowbyte of COUNT
  1089. CALL PRINT_BYTE ; Print it
  1090. JC END_PRT_LINE_ENDP ; If printer error then quit
  1091. ADD DI,2 ; Point to next tag
  1092. DEC CX ;
  1093. .WHEN <BL EQ HIGHCOUNT_CODE> ; Sending highbyte of COUNT
  1094. PUSH AX ; Save count
  1095. CWD ;
  1096. MOV BX,100h ;
  1097. DIV BX ; Put highbyte in AL
  1098. CALL PRINT_BYTE ; Print it
  1099. JC END_PRT_LINE_ENDP_1 ; If printer error then quit
  1100. ; the loop and restore registers
  1101. ADD DI,2 ; Point to next tag
  1102. ; the loop.
  1103. POP AX ; Restore count
  1104. DEC CX ;
  1105. .ENDSELECT ;
  1106. .ENDWHILE ;
  1107. JMP SHORT CR_LF ;
  1108. GOTO_END_PRT_LINE_ENDP_2: ; Conditional jump was out of range
  1109. JMP SHORT END_PRT_LINE_ENDP_2 ;
  1110. GOTO_END_PRT_LINE_ENDP_1: ; Conditional jump was out of range
  1111. JMP SHORT END_PRT_LINE_ENDP_1 ;
  1112. CR_LF: ;
  1113. .IF <DS:[BP].PRINTER_NEEDS_CR_LF EQ YES> ; ~~mda(003) We have an IBM type printer
  1114. ; so we need to do a CR and LF if it
  1115. ; already hasn't been done.
  1116. .IF <CR_FOUND EQ NO> ; It hasn't been done.
  1117. MOV AL,CR ;
  1118. CALL PRINT_BYTE ;
  1119. JC END_PRT_LINE_ENDP ; If printer error then quit
  1120. .ENDIF ;
  1121. .IF <LF_FOUND EQ NO> ; It hasn't been done.
  1122. MOV AL,LF ;
  1123. CALL PRINT_BYTE ;
  1124. JC END_PRT_LINE_ENDP ; If printer error then quit
  1125. .ENDIF ;
  1126. ;
  1127. .ENDIF ;
  1128. JMP NEW_PRT_LINE_ENDP ; Restore registers
  1129. JMP SHORT END_PRT_LINE_ENDP ;
  1130. END_PRT_LINE_ENDP_2: ; Restore registers
  1131. POP SI ;
  1132. END_PRT_LINE_ENDP_1: ; Restore registers
  1133. POP AX ;
  1134. END_PRT_LINE_ENDP: ;
  1135. POP DI ;
  1136. POP DX ;
  1137. POP CX ;
  1138. POP BX ;
  1139. POP AX ;
  1140. RET ;
  1141. END_PRT_LINE ENDP ;
  1142. ; /\ ~~mda(001) -----------------------------------------------------------------------
  1143. PAGE ;AN000;
  1144. ; \/ ~~mda(001) -----------------------------------------------------------------------
  1145. ; Since we now can do HP PCL, we have to get the number of
  1146. ; bytes that are going to be sent to the printer and convert
  1147. ; the number to ASCII if DATA_TYPE = DATA_ROW.
  1148. ;===============================================================================;AN000;
  1149. ; ;AN000;
  1150. ; GET_COUNT : GET THE NUMBER OF BYTES TO SEND TO THE PRINTER
  1151. ; ;AN000;
  1152. ;-------------------------------------------------------------------------------;AN000;
  1153. ; ;AN000;
  1154. ; INPUT: CUR_SCAN_LNE_LENGTH
  1155. ; NB_BOXES_PER_PRT_BUF ;AN000;
  1156. ; ;AN000;
  1157. ; output : si pointer to ascii string
  1158. ;
  1159. ; si --> len=4 (hex = 4d2h)
  1160. ; 1
  1161. ; 2
  1162. ; 3
  1163. ; 4
  1164. ;
  1165. ; count (from shared_data_area)
  1166. ;
  1167. ; ;AN000;
  1168. ; CALLED BY: NEW_PRT_LINE
  1169. ; END_PRT_LINE
  1170. ; ;AN000;
  1171. ;-------------------------------------------------------------------------------;AN000;
  1172. GET_COUNT proc near
  1173. push ax ;
  1174. push bx ;
  1175. push cx ;
  1176. push dx ;
  1177. push si ;
  1178. mov ax,cur_scan_lne_length ; Get # bytes to send to
  1179. cwd ; the printer
  1180. xor bh,bh ;
  1181. mov bl,nb_boxes_per_prt_buf ;
  1182. div bx ;
  1183. .IF <DX NE 0> ; So don't lose data when
  1184. INC AX ; have a remainder.
  1185. .ENDIF ;
  1186. ;
  1187. ;--------- AX is the # bytes to send to the printer. Now convert it to ascii.
  1188. ;
  1189. xor dx,dx ;clear upper 16 bits
  1190. lea si,ds:[bp].count ;get pointer
  1191. PUSH SI ; Save ptr.
  1192. MOV CX,5 ; Init. COUNT
  1193. INIT_COUNT: ;
  1194. MOV BYTE PTR [SI],0 ;
  1195. DEC SI ;
  1196. LOOP INIT_COUNT ;
  1197. POP SI ;
  1198. ;
  1199. mov bx,10 ; mod 10, div 10
  1200. xor cx,cx ;length counter = 0
  1201. hx_asc: ;
  1202. div bx ;div, mod
  1203. add dl,'0' ;add 48 for ASCII
  1204. mov [si],dl ;store it
  1205. dec si ;point to next string element
  1206. inc cx ;inc length counter
  1207. xor dx,dx ;consider only div part for next loop
  1208. cmp ax,0 ;end of loops ? (div=0)
  1209. jnz hx_asc ;no
  1210. mov ds:[bp].num_bytes_for_count,cl ;save the length
  1211. ;
  1212. pop si ;
  1213. pop dx ;
  1214. pop cx ;
  1215. pop bx ;
  1216. pop ax ;
  1217. ret ;
  1218. GET_COUNT endp ;
  1219. ; /\ ~~mda(001) -----------------------------------------------------------------------
  1220. PAGE
  1221. ;
  1222. ;===============================================================================;AN000;
  1223. ; ;AN000;
  1224. ; PRINT_BYTE : SEND A BYTE TO THE PRINTER AT LPT1 ;AN000;
  1225. ; ;AN000;
  1226. ;-------------------------------------------------------------------------------;AN000;
  1227. ; ;AN000;
  1228. ; INPUT: AL = Byte to be printed ;AN000;
  1229. ; ;AN000;
  1230. ; OUTPUT: PRINTER ;AN000;
  1231. ; ERROR_CODE = PRINTER_ERROR if an error is detected. ;AN000;
  1232. ; Carry flag is set in case of error. ;AN000;
  1233. ; ;AN000;
  1234. ;-------------------------------------------------------------------------------;AN000;
  1235. PRINT_BYTE PROC NEAR ;AN000;
  1236. PUSH AX ;AN000;
  1237. PUSH DX ;AN000;
  1238. ;AN000;
  1239. MOV DX,0000 ; PRINTER NUMBER ;AN000;
  1240. MOV AH,00 ; REQUEST PRINT ;AN000;
  1241. INT 17H ; CALL BIOS : SEND THE CHARACTER ;AN000;
  1242. ;AN000;
  1243. AND AH,00101001B ; Test error code returned in AH for ;AN000;
  1244. ; "Out of paper", "I/O error" and "Time-out". ;AN000;
  1245. JNZ PRINT_BYTE_ERROR; Set the error code if error ;AN000;
  1246. JMP SHORT PRINT_BYTE_END ; else, return normally ;AN000;
  1247. PRINT_BYTE_ERROR: ;AN000;
  1248. MOV ERROR_CODE,PRINTER_ERROR ;AN000;
  1249. STC ; Set the carry flag to indicate ERROR ;AN000;
  1250. PRINT_BYTE_END: ;AN000;
  1251. POP DX ;AN000;
  1252. POP AX ;AN000;
  1253. RET ;AN000;
  1254. PRINT_BYTE ENDP ;AN000;
  1255. PAGE ;AN000;
  1256. ;===============================================================================;AN000;
  1257. ; ;AN000;
  1258. ; READ_DOT: READ A PIXEL - RETURN A COLOR TRANSLATION TABLE INDEX ;AN000;
  1259. ; ;AN000;
  1260. ;-------------------------------------------------------------------------------;AN000;
  1261. ; ;AN000;
  1262. ; INPUT: CUR_MODE = Current video mode. ;AN000;
  1263. ; CUR_ROW, ;AN000;
  1264. ; CUR_COLUMN = Coordinates of the pixel to be read. ;AN000;
  1265. ; CUR_PAGE = Active page number ;AN000;
  1266. ; ;AN000;
  1267. ; OUTPUT: AL = Index into COLOR TRANSLATION TABLE. ;AN000;
  1268. ; ;AN000;
  1269. ; DEPENDENCIES : COLOR TRANSLATION TABLE entries must be bytes ;AN000;
  1270. ; ;AN000;
  1271. ; ;AN000;
  1272. ;-------------------------------------------------------------------------------;AN000;
  1273. ; ;AN000;
  1274. ; DESCRIPTION: Use VIDEO BIOS INTERRUPT 10H "READ DOT CALL". ;AN000;
  1275. ; ;AN000;
  1276. ; Depending on the video hardware, the dot returned by BIOS has ;AN000;
  1277. ; different meanings. ;AN000;
  1278. ; With an EGA it is an index into the Palette registers, ;AN000;
  1279. ; With a CGA it is a number from 0 to 3, mapping to a specific color ;AN000;
  1280. ; depending on the background color and the color palette currently ;AN000;
  1281. ; selected. ;AN000;
  1282. ; ;AN000;
  1283. ; The Color Translation table has been set up to hold the correct color ;AN000;
  1284. ; mapping for any "dot" in any mode. Therefore, the dot number returned ;AN000;
  1285. ; by INT 10H can be used with any mode as a direct index within that ;AN000;
  1286. ; table. ;AN000;
  1287. ; ;AN000;
  1288. ; With APA Monochrome mode 0FH there are 4 different dots: white, ;AN000;
  1289. ; blinking white, high-intensity white, and black. ;AN000;
  1290. ; ;AN000;
  1291. ; For mode 0FH, the dot returned by interrupt 10 "read dot" call is a byte ;AN000;
  1292. ; where only bits 0 and 2 are significant. These 2 bits must be appended ;AN000;
  1293. ; together in order to obtain a binary number (from 0 to 3) that will be used ;AN000;
  1294. ; as an index in the Color Translation table. ;AN000;
  1295. ; ;AN000;
  1296. ; For mode 11H, the dot is either 0 (for background color) or 7 (for the ;AN000;
  1297. ; foreground color) only the LSB is returned. That is, we return either ;AN000;
  1298. ; 0 or 1. ;AN000;
  1299. ; ;AN000;
  1300. ; LOGIC: ;AN000;
  1301. ; ;AN000;
  1302. ; Call VIDEO BIOS "READ DOT" ;AN000;
  1303. ; IF CUR_MODE = 0FH ;AN000;
  1304. ; THEN ;AN000;
  1305. ; Append bits 1 and 3. ;AN000;
  1306. ; IF CUR_MODE = 11H ;AN000;
  1307. ; THEN ;AN000;
  1308. ; Wipe out bits 1 and 2. ;AN000;
  1309. ; ;AN000;
  1310. READ_DOT PROC NEAR ;AN000;
  1311. PUSH BX ; Save registers ;AN000;
  1312. PUSH CX ;AN000;
  1313. PUSH DX ;AN000;
  1314. ;AN000;
  1315. MOV BH,CUR_PAGE ;AN000;
  1316. MOV DX,CUR_ROW ;AN000;
  1317. MOV CX,CUR_COLUMN ;AN000;
  1318. MOV AH,READ_DOT_CALL ;AN000;
  1319. INT 10H ; Call BIOS: AL <-- Dot read ;AN000;
  1320. ;AN000;
  1321. CMP CUR_MODE,0FH ; Is it Mode 0fH ? ;AN000;
  1322. JNE MODE_11H? ; No, look for mode 11h. ;AN000;
  1323. ;-------Mode 0Fh is the current mode: ;AN000;
  1324. ;-------Convert bits 2 and 0 into a 2 bit number: ;AN000;
  1325. MOV BL,AL ; BL := AL = "Pixel read" ;AN000;
  1326. AND BL,00000100B ; Wipe off all bits but bit 2 in BL ;AN000;
  1327. AND AL,00000001B ; Wipe off all bits but bit 0 in AL ;AN000;
  1328. SHR BL,1 ; Move bit 2 to bit 1 in BL ;AN000;
  1329. OR AL,BL ; Append bit 1 and bit 0 ;AN000;
  1330. JMP SHORT READ_DOT_END ; Quit. ;AN000;
  1331. ;AN000;
  1332. MODE_11H?: ;AN000;
  1333. CMP CUR_MODE,11H ; Is it Mode 0fH ? ;AN000;
  1334. JNE READ_DOT_END ; No, quit ;AN000;
  1335. ;AN000;
  1336. ;-------Mode 11H is the current mode: ;AN000;
  1337. AND AL,00000001B ; Keep only the Least significant bit ;AN000;
  1338. ;AN000;
  1339. READ_DOT_END: ;AN000;
  1340. POP DX ; Restore registers ;AN000;
  1341. POP CX ;AN000;
  1342. POP BX ;AN000;
  1343. RET ;AN000;
  1344. READ_DOT ENDP ;AN000;
  1345.