REBOL [
    Title: "Hex print"
    Purpose: {Take a string of characters and return it formatted
    in a way that if the result is printed one can have a hex representation
    of the string.}
]

;; [---------------------------------------------------------------------------]
;; [ This is a helper function for a project of printing a string, that could  ]
;; [ contain unprintable characters, in a hexadecimal format.                  ]
;; [ Input to the function is a string.  Output is a block.  The block         ]
;; [ contains strings of up to 60 characters, occurring in pairs.              ]
;; [ The first string of a pair is up to 30 characters of the input string,    ]
;; [ with each character followed by a space.  If the character is             ]
;; [ unprintable, a dot will be returned in its place.                         ]
;; [ The second string of a pair is a hexadecimal representation of the        ]
;; [ same 30 characters.                                                       ]
;; [ If you would print a pair of the returned strings one above the other,    ]
;; [ you would have a "hex dump" of the string.                                ]
;; [ The original goal of the project was to print strings of comments         ]
;; [ from a database text field, to search visually for unprintable junk.      ]
;; [---------------------------------------------------------------------------]

HEX-PRINT: func [
    STR
    /local BLK S1 S2 CNT
] [
    BLK: copy []
    S1: copy ""
    S2: copy ""
    CNT: 0
    foreach BYTE STR [
        either (BYTE < #"^(20)") or (BYTE > #"^(7E)") [
            either ((not-equal? (to-char BYTE) #"^(0D)")   ;; CR
            and (not-equal? (to-char BYTE) #"^(09)")       ;; HT
            and (not-equal? (to-char BYTE) #"^(0A)")) [     ;; LF   
                append S1 "? "
            ] [
                append S1 ". "
            ]
        ] [
            append S1 rejoin [BYTE " "]
        ]
        append S2 reverse copy/part reverse to-string to-hex to-integer to-binary BYTE 2
        CNT: CNT + 1
        if greater? CNT 30 [
            append BLK S1
            append BLK S2
            S1: copy ""
            S2: copy ""
            CNT: 0
        ]
    ]
    append BLK S1
    append BLK S2
    return BLK
]

;;Uncomment to test
;TESTDATA: {
;Abcdef
;123456
;!@#$%^
;}
;DUMP: HEX-PRINT TESTDATA
;foreach [PLAIN HEX] DUMP [
;    print PLAIN
;    print HEX
;]
;halt