package main import ( "bytes" "fmt" "strconv" "strings" ) type BlockFont struct { characters []int data [][][]byte } /* func BytesHexed(output []byte) { fmt.Printf("BH: ") for _, ch := range output { fmt.Printf("%02x ", ch) } fmt.Println("") } func BytesArrayHexed(output *[][]byte) { for _, out := range *output { BytesHexed(out) } } */ // Make []strings all the same length func normalizeBlock(block *[][]byte) { var max int // StringO(block) for _, line := range *block { l := len(line) if max < l { max = l } } // fmt.Printf("max = %d\n", max) for idx, _ := range *block { // l := len(line) for len((*block)[idx]) < max { //(*block)[idx] += byte(0x20) //append((*block)[idx], byte{0x20}) (*block)[idx] = append((*block)[idx], byte(0x20)) } } // StringO(block) // fmt.Println("== normalized ==") } // Get Character information from BlockFont return Normalize func (bf *BlockFont) GetCharacter(c int) [][]byte { var result [][]byte if c == 32 { // Space character result = append(result, []byte{0x20, 0x20}) return result } // 33-126 are the possible characters. if c >= 33 && c <= 126 { c -= 33 idx := bf.characters[c] if idx == -1 { // This character is not supported by this font. return result } result = bf.data[bf.characters[c]] // fmt.Println("normalizeCharBlock") normalizeBlock(&result) // fmt.Println("normalizeChar done") return result } else { return result } } // expandBlock the number of strings, and make it match the length of [0]. func __expandBlock(block *[]string) { // l := len((*block)[0]) l := len([]rune((*block)[0])) *block = append(*block, strings.Repeat(" ", l)) } func expandBlock(block *[][]byte) { // l := len((*block)[0]) l := len((*block)[0]) blank := []byte{0x20} *block = append(*block, bytes.Repeat(blank, l)) } // Given text, translate to thedraw font. func (bf *BlockFont) Output(input string) ([][]byte, int) { var out [][]byte var max int for _, ch := range input { // fmt.Printf("%d %x\n", ch, ch) block := bf.GetCharacter(int(ch)) // fmt.Println("ok") l := len(block) max += l if l != 0 { if len(out) == 0 { // First time for _, b := range block { out = append(out, b) } } else { if len(out) != 0 { for l > len(out) { // We need to expand the out // fmt.Println("expandBlock") expandBlock(&out) } } // fmt.Println("Append block to out") // Ok, we have something! for idx, b := range block { out[idx] = append(out[idx], byte(0x20)) // out[idx] = append(out[idx], b) for _, inner := range b { out[idx] = append(out[idx], inner) } // out[idx] += byte(0x20) + b // fmt.Printf("%s\n", CP437_to_Unicode(b)) } } } // fmt.Println("normalizeBlock") normalizeBlock(&out) // fmt.Println("normalizeBlock done") } return out, len(out[0]) } type ColorFont struct { characters []int data [][][]byte } // Make []strings all the same length func ___normalizeColor(block *[]string) int { var max int for _, line := range *block { l := len([]rune(line)) if max < l { max = l } } for idx, line := range *block { l := len([]rune(line)) if l < max { (*block)[idx] += strings.Repeat(" \x0f", max-l/2) } } return max } func normalizeColor(block *[][]byte) int { var max int for _, line := range *block { l := len(line) if max < l { max = l } } for idx, _ := range *block { // l := len(line) blank := []byte{0x20, 0x0f} for len((*block)[idx]) < max { (*block)[idx] = append((*block)[idx], blank...) /* for _, b := range blank { (*block)[idx] = append((*block)[idx], b) } */ // (*block)[idx] += strings.Repeat(" \x0f", max-l/2) } } return max } func (cf *ColorFont) GetCharacter(c int) ([][]byte, int) { var result [][]byte if c == 32 { blank := []byte{0x20, 0x0f, 0x20, 0x0f} result = append(result, blank) // " \x0f \x0f") return result, len(result[0]) / 2 } if c >= 33 && c <= 126 { c -= 33 idx := cf.characters[c] if idx == -1 { return result, 0 } result = cf.data[cf.characters[c]] // fmt.Println("Character:") // BytesArrayHexed(&result) // fmt.Println("normalizing...") max := normalizeColor(&result) // BytesArrayHexed(&result) // StringHexO(&result) return result, max } else { return result, 0 } } /* func expandColor(block *[]string) { l := len((*block)[0]) *block = append(*block, strings.Repeat(" \x0f", l/2)) } */ func thedraw_to_ansi(c int) int { trans := []int{0, 4, 2, 6, 1, 5, 3, 7} return trans[c] } func colorout(c int) string { bg := thedraw_to_ansi(c / 16) fg := c % 16 bold := (fg & 0x8) == 0x8 fg = thedraw_to_ansi(fg & 0x7) if bold { return fmt.Sprintf("\x1b[0;1;%d;%dm", fg+30, bg+40) } else { return fmt.Sprintf("\x1b[0;%d;%dm", fg+30, bg+40) } } type ColorParts struct { Background int Foreground int Bold bool } func ColorSplit(color int) ColorParts { return ColorParts{Background: thedraw_to_ansi(color / 16), Foreground: thedraw_to_ansi(color & 7), Bold: (color%16)&0x08 == 0x08} } func ColorOutput(previous int, color int) string { prev := ColorSplit(previous) c := ColorSplit(color) var codes []int8 if c.Bold { if !prev.Bold { codes = append(codes, 1) } } else { if prev.Bold { // bold was set previously, there's only one way to reset it codes = append(codes, 0) prev.Background = 0 prev.Foreground = 7 } } if prev.Background == 0 && prev.Foreground == 0 { // output everything codes = append(codes, int8(c.Foreground)+30) codes = append(codes, int8(c.Background)+40) } else { if c.Foreground != prev.Foreground { codes = append(codes, int8(c.Foreground)+30) } if c.Background != prev.Background { codes = append(codes, int8(c.Background)+40) } } if len(codes) == 0 { // Everything matched return "" } var text []string for _, code := range codes { text = append(text, strconv.Itoa(int(code))) } return "\x1b[" + strings.Join(text, ";") + "m" } func Colorize(input []byte) []byte { var result []byte // runes := []rune(input) var previous int // BytesHexed(input) for pos := 0; pos < len(input); pos += 2 { ch := input[pos] color := int(input[pos+1]) // fmt.Printf("%d : CH %d / %x, Color %d / %x\n", pos, ch, ch, color, color) colorstring := ColorOutput(previous, color) for _, c := range []byte(colorstring) { result = append(result, c) } // result = append(result, []byte(colorstring)) // result += []byte(ColorOutput(previous, color)) // result += ColorOutput(previous, color) + string(ch) result = append(result, ch) // result += string(ch) previous = color // result += colorout(color) + string(ch) } return result } func __expandColor(block *[]string, need int) { *block = append(*block, strings.Repeat(" \x0f", need)) } func expandColor(block *[][]byte, need int) { blank := []byte{0x20, 0x0f} // *block = append(*block, strings.Repeat(" \x0f", need)) *block = append(*block, bytes.Repeat(blank, need)) } func (bf *ColorFont) Output(input string) ([][]byte, int) { var out [][]byte var max int for _, ch := range input { // fmt.Printf("%d %x\n", ch, ch) block, blklen := bf.GetCharacter(int(ch)) if blklen == 0 { continue } l := len(block) max += blklen if l != 0 { if len(out) == 0 { // First time for _, b := range block { out = append(out, b) } } else { if len(out) != 0 { for l > len(out) { // We need to expand the out expandColor(&out, len(out[0])/2) // ExpandColor(&out) } } for len(out) > len(block) { // We need to expand the block out expandColor(&block, len(block)/2) } // Normalizing the character blocks normalizeColor(&block) if len(out) != len(block) { panic(fmt.Sprintf("len(out) %d != len(block) %d", len(out), len(block))) } // Ok, we have something! for idx, b := range block { // blank := []byte{0x20, 0x0f} out[idx] = append(out[idx], byte(0x20)) out[idx] = append(out[idx], byte(0x0f)) for _, inner := range b { out[idx] = append(out[idx], inner) } //out[idx] += " \x0f" + b // fmt.Printf("%s\n", CP437_to_Unicode(b)) } } // NormalizeColor(&out) } } if len(out) == 0 { return out, 0 } // StringHexO(&out) max = len(out[0]) / 2 for idx, _ := range out { out[idx] = Colorize(out[idx]) } return out, max } func CP437Bytes_to_Unicode(cp437 []byte) string { var result string for _, char := range cp437 { // fmt.Printf("%d, %x ", char, char) switch int(char) { case 0x01: result += "\u263A" case 0x02: result += "\u263B" case 0x03: result += "\u2665" case 0x04: result += "\u2666" case 0x05: result += "\u2663" case 0x06: result += "\u2660" case 0x09: result += "\u25CB" case 0x0b: result += "\u2642" case 0x0c: result += "\u2640" case 0x0e: result += "\u266B" case 0x0f: result += "\u263C" case 0x10: result += "\u25BA" case 0x11: result += "\u25C4" case 0x12: result += "\u2195" case 0x13: result += "\u203C" case 0x14: result += "\xc2\xb6" case 0x15: result += "\xc2\xa7" case 0x16: result += "\u25AC" case 0x17: result += "\u21A8" case 0x18: result += "\u2191" case 0x19: result += "\u2193" case 0x1a: result += "\u2192" case 0x1c: result += "\u221F" case 0x1d: result += "\u2194" case 0x1e: result += "\u25B2" case 0x1f: result += "\u25BC" case 0x7f: result += "\u2302" case 0x80: result += "\xc3\x87" case 0x81: result += "\xc3\xbc" case 0x82: result += "\xc3\xa9" case 0x83: result += "\xc3\xa2" case 0x84: result += "\xc3\xa4" case 0x85: result += "\xc3\xa0" case 0x86: result += "\xc3\xa5" case 0x87: result += "\xc3\xa7" case 0x88: result += "\xc3\xaa" case 0x89: result += "\xc3\xab" case 0x8a: result += "\xc3\xa8" case 0x8b: result += "\xc3\xaf" case 0x8c: result += "\xc3\xae" case 0x8d: result += "\xc3\xac" case 0x8e: result += "\xc3\x84" case 0x8f: result += "\xc3\x85" case 0x90: result += "\xc3\x89" case 0x91: result += "\xc3\xa6" case 0x92: result += "\xc3\x86" case 0x93: result += "\xc3\xb4" case 0x94: result += "\xc3\xb6" case 0x95: result += "\xc3\xb2" case 0x96: result += "\xc3\xbb" case 0x97: result += "\xc3\xb9" case 0x98: result += "\xc3\xbf" case 0x99: result += "\xc3\x96" case 0x9a: result += "\xc3\x9c" case 0x9b: result += "\xc2\xa2" case 0x9c: result += "\xc2\xa3" case 0x9d: result += "\xc2\xa5" case 0x9e: result += "\u20A7" case 0x9f: result += "\u0192" case 0xa0: result += "\xc3\xa1" case 0xa1: result += "\xc3\xad" case 0xa2: result += "\xc3\xb3" case 0xa3: result += "\xc3\xba" case 0xa4: result += "\xc3\xb1" case 0xa5: result += "\xc3\x91" case 0xa6: result += "\xc2\xaa" case 0xa7: result += "\xc2\xba" case 0xa8: result += "\xc2\xbf" case 0xa9: result += "\u2310" case 0xaa: result += "\xc2\xac" case 0xab: result += "\xc2\xbd" case 0xac: result += "\xc2\xbc" case 0xad: result += "\xc2\xa1" case 0xae: result += "\xc2\xab" case 0xaf: result += "\xc2\xbb" case 0xb0: result += "\u2591" case 0xb1: result += "\u2592" case 0xb2: result += "\u2593" case 0xb3: result += "\u2502" case 0xb4: result += "\u2524" case 0xb5: result += "\u2561" case 0xb6: result += "\u2562" case 0xb7: result += "\u2556" case 0xb8: result += "\u2555" case 0xb9: result += "\u2563" case 0xba: result += "\u2551" case 0xbb: result += "\u2557" case 0xbc: result += "\u255D" case 0xbd: result += "\u255C" case 0xbe: result += "\u255B" case 0xbf: result += "\u2510" case 0xc0: result += "\u2514" case 0xc1: result += "\u2534" case 0xc2: result += "\u252C" case 0xc3: result += "\u251C" case 0xc4: result += "\u2500" case 0xc5: result += "\u253C" case 0xc6: result += "\u255E" case 0xc7: result += "\u255F" case 0xc8: result += "\u255A" case 0xc9: result += "\u2554" case 0xca: result += "\u2569" case 0xcb: result += "\u2566" case 0xcc: result += "\u2560" case 0xcd: result += "\u2550" case 0xce: result += "\u256C" case 0xcf: result += "\u2567" case 0xd0: result += "\u2568" case 0xd1: result += "\u2564" case 0xd2: result += "\u2565" case 0xd3: result += "\u2559" case 0xd4: result += "\u2558" case 0xd5: result += "\u2552" case 0xd6: result += "\u2553" case 0xd7: result += "\u256B" case 0xd8: result += "\u256A" case 0xd9: result += "\u2518" case 0xda: result += "\u250C" case 0xdb: result += "\u2588" case 0xdc: result += "\u2584" case 0xdd: result += "\u258C" case 0xde: result += "\u2590" case 0xdf: result += "\u2580" case 0xe0: result += "\u03B1" case 0xe1: result += "\xc3\x9f" case 0xe2: result += "\u0393" case 0xe3: result += "\u03C0" case 0xe4: result += "\u03A3" case 0xe5: result += "\u03C3" case 0xe6: result += "\xc2\xb5" case 0xe7: result += "\u03C4" case 0xe8: result += "\u03A6" case 0xe9: result += "\u0398" case 0xea: result += "\u03A9" case 0xeb: result += "\u03B4" case 0xec: result += "\u221E" case 0xed: result += "\u03C6" case 0xee: result += "\u03B5" case 0xef: result += "\u2229" case 0xf0: result += "\u2261" case 0xf1: result += "\xc2\xb1" case 0xf2: result += "\u2265" case 0xf3: result += "\u2264" case 0xf4: result += "\u2320" case 0xf5: result += "\u2321" case 0xf6: result += "\xc3\xb7" case 0xf7: result += "\u2248" case 0xf8: result += "\xc2\xb0" case 0xf9: result += "\u2219" case 0xfa: result += "\xc2\xb7" case 0xfb: result += "\u221A" case 0xfc: result += "\u207F" case 0xfd: result += "\xc2\xb2" case 0xfe: result += "\u25A0" case 0xff: result += "\xc2\xa0" default: result += string(char) } } // fmt.Printf("\n") return result }