.MODEL    SMALL

.DATA

REAL_CURSOR_X          DB     0
REAL_CURSOR_Y          DB     0
     PUBLIC    PHANTOM_CURSOR_X, PHANTOM_CURSOR_Y
PHANTOM_CURSOR_X       DB     0
PHANTOM_CURSOR_Y       DB     0

.CODE

;-----------------------------------------------------------------------;
; Estos cuatro procedimientos mueven los cursores fantasmas             ;
;                                                                       ;
; Usa:    ERASE_PHANTOM, WRITE_PHANTOM                                  ;
; Lee:    PHANTOM_CURSOR_X, PHANTOM_CURSOR_Y                            ;
; Escrobe:PHANTOM_CURSOR_X, PHANTOM_CURSOR_Y                            ;
;-----------------------------------------------------------------------;

     PUBLIC    PHANTOM_UP
PHANTOM_UP     PROC
     CALL ERASE_PHANTOM       ;Borra en la posici¢n actual
     DEC  PHANTOM_CURSOR_Y    ;Mueve el cursor una l¡nea hacia arriba
     JNS  WASNT_AT_TOP        ;No estaba al principio, escribe el cursor
     MOV  PHANTOM_CURSOR_Y,0  ;Estaba al principio, por tanto, vuelve a
WASNT_AT_TOP:                 ; ponerlo ah¡
     CALL WRITE_PHANTOM       ;Escribe el cursor fantasma en la nueva posici¢n
     RET
PHANTOM_UP     ENDP

     PUBLIC    PHANTOM_DOWN
PHANTOM_DOWN   PROC
     CALL ERASE_PHANTOM       ;Borra en la posici¢n actual
     INC  PHANTOM_CURSOR_Y    ;Mueve el cursor una l¡nea hacia abajo
     CMP  PHANTOM_CURSOR_Y,16 ;¨Estaba al final?
     JB   WASNT_AT_BOTTOM     ;No, por tanto escribe el cursor fantasma
     MOV  PHANTOM_CURSOR_Y,15 ;Estaba al final, por tanto vuelve a ponerlo ah¡
WASNT_AT_BOTTOM:
     CALL WRITE_PHANTOM       ;Escribe el cursor fantasma
     RET
PHANTOM_DOWN   ENDP

     PUBLIC    PHANTOM_LEFT
PHANTOM_LEFT   PROC
     CALL ERASE_PHANTOM       ;Borra en la posici¢n actual
     DEC  PHANTOM_CURSOR_X    ;Mueve el cursor una columna a la izquierda
     JNS  WASNT_AT_LEFT       ;No estaba en el lado derecho, escribe el cursor
     MOV  PHANTOM_CURSOR_X,0  ;Estaba a la izquierda, por tanto vuelve a
WASNT_AT_LEFT:                ; ponerlo ah¡
     CALL WRITE_PHANTOM       ;Escribe el cursor fantasma
     RET
PHANTOM_LEFT   ENDP

     PUBLIC    PHANTOM_RIGHT
PHANTOM_RIGHT  PROC
     CALL ERASE_PHANTOM       ;Borra en la posici¢n actual
     INC  PHANTOM_CURSOR_X    ;Mueve el cursor una columna a la derecha
     CMP  PHANTOM_CURSOR_X,16 ;¨Estaba ya en el lado derecho?
     JB   WASNT_AT_RIGHT
     MOV  PHANTOM_CURSOR_X,15 ;Estaba a la derecha, por tanto vuelve a ponerlo
WASNT_AT_RIGHT:               ; ah¡
     CALL WRITE_PHANTOM       ;Escribe el cursor fantasma
     RET
PHANTOM_RIGHT  ENDP



     PUBLIC    MOV_TO_HEX_POSITION
     EXTRN     GOTO_XY:PROC
.DATA
     EXTRN     LINES_BEFORE_SECTOR:BYTE
.CODE
;-----------------------------------------------------------------------;
; Este procedimiento mueve el cursor real a la posici¢n del cursor fan- ;
; tasma de la pantalla hexadecimal.                                     ;
;                                                                       ;
; Usa:         GOTO_XY                                                  ;
; Lee:         LINES_BEFORE_SECTOR, PHANTOM_CURSOR_X, PHANTOM_CURSOR_Y  ;
;-----------------------------------------------------------------------;
MOV_TO_HEX_POSITION    PROC
     PUSH AX
     PUSH CX
     PUSH DX
     MOV  DH,LINES_BEFORE_SECTOR ;Fila donde se encuentra el cursor
                                 ; fantasma (0,0)
     ADD  DH,2                   ;M s la fila de la barra hexadecimal
                                 ; y horizontal
     ADD  DH,PHANTOM_CURSOR_Y    ;DH = fila del cursor fantasma
     MOV  DL,8                   ;Indenta en el lado derecho
     MOV  CL,3                   ;Cada columna usa 3 caracteres, por
                                 ; tanto hemos de multiplicar CURSOR_X
     MOV  AL,PHANTOM_CURSOR_X    ; por 3
     MUL  CL
     ADD  DL,AL                  ;Suma a la indentaci¢n para obtener la
     CALL GOTO_XY                ; columna del cursor fantasma
     POP  DX
     POP  CX
     POP  AX
     RET
MOV_TO_HEX_POSITION    ENDP

     PUBLIC    MOV_TO_ASCII_POSITION
     EXTRN     GOTO_XY:PROC
.DATA
     EXTRN     LINES_BEFORE_SECTOR:BYTE
.CODE
;-----------------------------------------------------------------------;
; Este procedimiento mueve el cursor real al principio del cursor fan-  ;
; tasma de la ventana ASCII.                                            ;
;                                                                       ;
; Usa:         GOTO_XY                                                  ;
; Lee:         LINES_BEFORE_SECTOR, PHANTOM_CURSOR_X, PHANTOM_CURSOR_Y  ;
;-----------------------------------------------------------------------;
MOV_TO_ASCII_POSITION  PROC
     PUSH AX
     PUSH DX
     MOV  DH,LINES_BEFORE_SECTOR   ;Fila donde se encuentra el cursor
                                   ; fantasma (0,0)
     ADD  DH,2                     ;M s la fila de la barra hexadecimal
                                   ; y horizontal
     ADD  DH,PHANTOM_CURSOR_Y      ;DH = fila del cursor fantasma
     MOV  DL,59                    ;Indenta en el lado izquierdo
     ADD  DL,PHANTOM_CURSOR_X      ;Suma CURSOR_X para obtener la posici¢n
     CALL GOTO_XY                  ; X del cursor fantasma
     POP  DX
     POP  AX
     RET
MOV_TO_ASCII_POSITION  ENDP

     PUBLIC    SAVE_REAL_CURSOR
;-----------------------------------------------------------------------;
; Este procedimiento salva la posici¢n del cursor real en las variables ;
; REAL_CURSOR_X y REAL_CURSOR_Y.                                        ;
;                                                                       ;
; Escribe:     REAL_CURSOR_X, REAL_CURSOR_Y                             ;
;-----------------------------------------------------------------------;
SAVE_REAL_CURSOR       PROC
     PUSH AX
     PUSH BX
     PUSH CX
     PUSH DX
     MOV  AH,3                ;Lee la posici¢n del cursor
     XOR  BH,BH               ; en la p gina 0
     INT  10h                 ;Y la devuelve en los registros DL,DH
     MOV  REAL_CURSOR_Y,DL    ;Salva la posici¢n
     MOV  REAL_CURSOR_X,DH
     POP  DX
     POP  CX
     POP  BX
     POP  AX
     RET
SAVE_REAL_CURSOR       ENDP

     PUBLIC    RESTORE_REAL_CURSOR
     EXTRN     GOTO_XY:PROC
;-----------------------------------------------------------------------;
; Este procedimiento restablece el cursor real a su anterior posici¢n   ;
; la cual se encuentra en las variables REAL_CURSOR_X y REAL_CURSOR_Y.  ;
;                                                                       ;
; Usa:         GOTO_XY                                                  ;
; Lee:         REAL_CURSOR_X, REAL_CURSOR_Y                             ;
;-----------------------------------------------------------------------;
RESTORE_REAL_CURSOR    PROC
     PUSH DX
     MOV  DL,REAL_CURSOR_Y
     MOV  DH,REAL_CURSOR_X
     CALL GOTO_XY
     POP  DX
     RET
RESTORE_REAL_CURSOR    ENDP

     PUBLIC    WRITE_PHANTOM
     EXTRN     WRITE_ATTRIBUTE_N_TIMES:PROC
;-----------------------------------------------------------------------;
; Este procedimiento usa CURSOR_X y CURSOR_Y, hasta MOV_TO_..., como    ;
; coordenadas del cursor fantasma. WRITE_PHANTOM imprime este.          ;
;                                                                       ;
; Usa:    WRITE_ATTRIBUTE_N_TIMES, SAVE_REAL_CURSOR                     ;
;         RESTORE_REAL_CURSOR, MOV_TO_HEX_POSITION                      ;
;         MOV_TO_ASCII_POSITION                                         ;
;-----------------------------------------------------------------------;
WRITE_PHANTOM  PROC
     PUSH CX
     PUSH DX
     CALL SAVE_REAL_CURSOR
     CALL MOV_TO_HEX_POSITION      ;Coordenadas del cursor en la ventana
                                   ; hexadecimal
     MOV  CX,4                     ;Hace que el cursor tenga cuatro
                                   ; caracteres de longitud
     MOV  DL,70h
     CALL WRITE_ATTRIBUTE_N_TIMES
     CALL MOV_TO_ASCII_POSITION    ;Coord. del cursor en la ventana ASCII
     MOV  CX,1                     ;El cursor tiene un solo car cter de largo
     CALL WRITE_ATTRIBUTE_N_TIMES
     CALL RESTORE_REAL_CURSOR
     POP  DX
     POP  CX
     RET
WRITE_PHANTOM  ENDP

     PUBLIC    ERASE_PHANTOM
     EXTRN     WRITE_ATTRIBUTE_N_TIMES:PROC
;-----------------------------------------------------------------------;
; Este procedimiento borra el cursor fantasma. Hace todo lo contrario   ;
; WRITE_PHANTOM.                                                        ;
;                                                                       ;
; Usa:    WRITE_ATTRIBUTE_N_TIMES, SAVE_REAL_CURSOR                     ;
;         RESTORE_REAL_CURSOR, MOV_TO_HEX_POSITION                      ;
;         MOV_TO_ASCII_POSITION                                         ;
;-----------------------------------------------------------------------;
ERASE_PHANTOM  PROC
     PUSH CX
     PUSH DX
     CALL SAVE_REAL_CURSOR
     CALL MOV_TO_HEX_POSITION      ;Coord. del cursor en la ventana hexadecimal
     MOV  CX,4                     ;Cambia el cursor a blanco sobre negro
     MOV  DL,7
     CALL WRITE_ATTRIBUTE_N_TIMES
     CALL MOV_TO_ASCII_POSITION
     MOV  CX,1
     CALL WRITE_ATTRIBUTE_N_TIMES
     CALL RESTORE_REAL_CURSOR
     POP  DX
     POP  CX
     RET
ERASE_PHANTOM  ENDP


     END
