;-----------------------------------------------------------------------
; Copyright 2000, Mark McDonald - All rights reserved
; TBOX - Display a text box on screen with optional shadow
; Row  = Starting screen row of box
; Col  = Starting screen column of box
; Rows = Number of rows for the box
; Cols = Number of columns for the box
; Attr = Color attribute of the box
; Opt  = Box Type 1-15
; Shad = 0 = no shadow, 1 = shadow (left/bottom)
;SUB TBOX(BYVAL Row  AS INTEGER, BYVAL Col  AS INTEGER, BYVAL Rows AS INTEGER, BYVAL Cols AS INTEGER, BYVAL Attr AS BYTE, BYVAL OPT AS INTEGER,BYVAL Shad AS INTEGER) PUBLIC
;-----------------------------------------------------------------------
MCODE Segment Byte
        Assume  CS: MCODE

        Public  tbox

tbox     Proc Far

ARG     Shad:BYTE, OPT:BYTE, ATTR:BYTE, COLS:WORD, ROWS:WORD, COL:WORD, ROW:WORD = Retbytes
        jmp JODATA
;--- Character Table ---
     ;                                                 1   1   1   1   1   1
     ;             1   2   3   4   5   6   7   8   9   0   1   2   3   4   5
     TLcnr   DB   '','','','','+','*','','','','','','','','',' '
     BLcnr   DB   '','','','','+','*','','','','','','','','',' '
     TRcnr   DB   '','','','','+','*','','','','','','','','',' '
     BRcnr   DB   '','','','','+','*','','','','','','','','',' '
     Horzc   DB   '','','','','-','*','','','','','','','','',' '
     Vertc   DB   '','','','','|','*','','','','','','',' ',' ',' '
;--- Working Variables ---
     TLC        DB 0h
     TRC        DB 0h
     BLC        DB 0h
     BRC        DB 0h
     VERT       DB 0h
     HORIZ      DB 0h
     Tcols      DB 0h
     Shadrn     DB 0h
;--- Start Program Code ---
JODATA:
;--- Save All Registers for Power BASIC ---
        push    BP                      ;
        mov     BP,SP                   ;
        push    DS                      ; save DS for PowerBASIC
;--- Use Screen Border as Box? ---
        mov     AL,OPT                  ; does OPT = 0?
        cmp     AL,0
        ja      NXTOP                   ; no
        mov     AH,10h                  ; yes, use BIOS INT 10h
        mov     AL,01h                  ; set border flag
        mov     BH,ATTR                 ; move color into BH
        int     10h                     ; execute interrupt
        jmp     TBoxDone                ; exit proc
;--- Decrement Option ---
NXTOP:
        dec     OPT
;--- Top Left Corner ---
        mov     AL,OPT                  ;
        mov     BX,OFFSET TLcnr         ; put offset of table into BX
        xlat    CS: [BX]                ; get top left character
        mov     TLC,AL                  ; put character in working var

;--- Top Right Corner ---
        mov     AL,OPT                  ;
        mov     BX,OFFSET TRcnr         ; put offset of table into BX
        xlat    CS: [BX]                ; get top right character
        mov     TRC,AL

;--- Bottom Left Corner ---
        mov     AL,OPT                  ;
        mov     BX,OFFSET BLcnr         ; put offset of table into BX
        xlat    CS: [BX]                ; get bottom left character
        mov     BLC,AL

;--- Bottom Right Corner ---
        mov     AL,OPT                  ;
        mov     BX,OFFSET BRcnr         ; put offset of table into BX
        xlat    CS: [BX]                ; get bottom right character
        mov     BRC,AL

;--- Vertical Character ---
        mov     AL,OPT                  ;
        mov     BX,OFFSET Vertc         ; put offset of table into BX
        xlat    CS: [BX]                ; get vertical character
        mov     VERT,AL

;--- Horizontal Character ---
        mov     AL,OPT                  ;
        mov     BX,OFFSET Horzc         ; put offset of table into BX
        xlat    CS: [BX]                ; get horizontal character
        mov     HORIZ,AL
;--- Determine Number of Shadow Characters ---
    mov  [Shadrn],2                     ; 2 shadow characters after box
    mov  AX,COL                         ; determine right most column
    add  AX,COLs                        ;
    cmp  AX,80                          ;
    ja   S0                             ; if 80 or more no shadow
    cmp  AX,79                          ; if 79 then 1 character shadow
    ja   S1
    jmp  S2                             ; other wise use 2 cols

S0:
    mov  [Shadrn],0                     ; no shadow cols available
    jmp  S2

S1:
    mov  [Shadrn],1                     ; 1 shadow col available

S2:
    mov  AX, 47104                      ; put screen segment in AX
    mov  ES, AX                         ; and in ES

    mov  AX, ROW                        ; put row in AX
    dec  AX                             ; minus one
    mov  CX, 160                        ; AX =
    mul  CX                             ;   AX * 160
    mov  DI, AX                         ; put it in DI
    mov  AX, COL                        ; put column in AX
    dec  AX                             ; minus one
    shl  AX, 1                          ; times 2
    add  DI, AX                         ; add to DI

    mov  DX, ROWS                       ; put rows in DX
    dec  DX                             ; minus top row
    dec  DX                             ; minus bottom row

    mov  CX, COLS                       ; put columns in CX
    dec  CX                             ; minus left column
    dec  CX                             ; minus right column

    mov  AH, ATTR                       ; put attribute in AH

    push CX                             ; save CX (columns)
    push DI                             ;  and DI (screen location)
    mov  AL, TLC                        ; put top left char in AL
;--- Write Top Line ---
    stosw                               ; write it to the screen
    mov  AL, HORIZ                      ; put top char in AL
    rep  stosw                          ; write it to the screen CX times
    mov  AL, TRC                        ; put top right char in AL
    stosw                               ; write it to the screen
    pop  DI                             ; restore DI
    pop  CX                             ;  and CX
;--- Write Middle Lines ---
HorizLoop:
    add  DI, 160                        ; move to next row on the screen
    push CX                             ; save CX
    push DI                             ;  and DI
;--- Write Left Vertical Character ---
    mov  AL, VERT                       ; put left char in AL
    stosw                               ; write it to the screen
;--- Write Middle Characters ---
    mov  AL, 32                         ; put a space in AL
    rep  stosw                          ; write it to the screen CX times
;--- Write Right Vertical Character ---
    mov  AL, OPT                        ; special right character?
    cmp  AL, 10                         ; OPT = 11?
    jz   JOP11                          ; jump if opt = 11
    cmp  AL, 11                         ; OPT = 12?
    jz   JOP11                          ; jump if opt = 12
    mov  AL, VERT                       ; put right char in AL
    jmp JOP11F
JOP11:
    mov  AL, 222                        ; OPT 11/12 Right Character
JOP11F:
    stosw                               ; write it to the screen
;--- Write Shadow Characters? ---
    mov  AL, Shad                       ; shadow flag set?
    cmp  AL, 0
    jz   NoShadow1                      ; jump if shadow flag = 0
    mov  AL, Shadrn                     ; how many right hand shadow
    cmp  AL, 0                          ; characters?
    jz   NoShadow1                      ; 0 = no columns available
;--- Yes Write a Shadow Character ---
    mov  AL, 8                          ; put attribute (grey) in AL
    inc  DI                             ; incr screen position pointer
    stosb                               ; put at screen loc ptd to by DI
    mov  AL, Shadrn                     ; check if can write another col
    cmp  AL, 1
    jz   NoShadow1                      ; 0 = no more cols for shadow
    inc  DI                             ; chg one more col to shadow
    mov  AL, 8                          ; put attribute (grey) in AL
    stosb                               ;
NoShadow1:
    pop  DI                             ; restore DI
    pop  CX                             ;  and CX
    dec  DX                             ; one less row
    jnz  HorizLoop                      ; loop until DX (rows) = 0

    add  DI, 160                        ; move to next row on the screen
    push DI                             ;
    push CX                             ;
    mov  AL, BLC                        ; put bottom left char in AL
    stosw                               ; write it to the screen
;--- Determine Bottom Row Character ---
    mov  AL, OPT
    cmp  AL, 6                          ; OPT = 7?
    jz   S7                             ; yes, use special character
    cmp  AL, 11                         ; OPT = 12?
    jz   S12                            ; yes, use special character
    mov  AL, HORIZ                      ; put bottom char in AL from table
    jmp  SF
S7:
    mov  AL, 220                        ; use this instead of table char
    jmp  SF

S12:
    mov  AL, 223                        ; use this instead of table char
    jmp  SF

;--- Write Bottom Row Character ---
SF:
    rep  stosw                          ; write it to the screen CX times
    mov  AL, BRC                        ; put bottom right char in AL
    stosw                               ; write it to the screen
    mov  AL,Shadrn                      ; check for last row shadow
    cmp  AL, 0                          ; any cols available?
    jz   NoShadow2                      ; no
    mov  AL,Shad                        ; shadow option set?
    cmp  AL, 0
    je   NoShadow2                      ; no
    mov  AL, 8                          ; set attribute (grey) of shadow
    inc  DI                             ; point to next screen position
    stosb                               ; write attribute to screen
    mov  AL, Shadrn                     ; any more cols available?
    cmp  AL, 1
    jz   NoShadow2                      ; no
    mov  AL, 8                          ; set attribute (grey) of shadow
    inc  DI                             ; point to next column
    stosb                               ; write attribute to screen
;--- Write Bottom Shadow Row? ---
NoShadow2:
    pop  CX                             ; restore CX
    pop  DI                             ; and DI
    mov  AL, Shad                       ; shadow option set?
    cmp  AL, 0                          ;
    je   TBoxDone                       ; no, exit program
    add  DI, 164                        ; yes, point to next row/col
    mov  AL, 8                          ; put attribute into AL
    inc  CX                             ; move over one col
    inc  CX                             ; move over another col
    mov  AL,Shadrn                      ; how many cols at end?
    cmp  AL, 2                          ; are there 2 cols?
    jz   FinishShadow                   ; yes
    dec  CX                             ; no
    cmp  AL, 1                          ; is there 1 col?
    jz   FinishShadow                   ; yes
    dec  CX                             ; no
FinishShadow:
    mov  AL, 8                          ; put attribute into AL
    inc  DI                             ; set column pointer
    stosb                               ; write attibute to screen
    loop FinishShadow                   ; do it CX times
TBoxDone:
;--- Restore ALL Registers Saved for Power BASIC ---
        pop     DS                      ; restore DS
        pop     BP                      ; restore BP
        retf    Retbytes                ; exit far proc freeing stack bytes
tbox     EndP
MCODE EndS
        End