| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 | 
							- package door
 
- import (
 
- 	"log"
 
- 	"regexp"
 
- 	"strconv"
 
- 	"strings"
 
- 	"syscall"
 
- )
 
- var writerChannel chan string
 
- func Writer(handle int) {
 
- 	for output := range writerChannel {
 
- 		buffer := []byte(output)
 
- 		n, err := syscall.Write(handle, buffer)
 
- 		if (err != nil) || (n != len(buffer)) {
 
- 			close(writerChannel)
 
- 			break
 
- 		}
 
- 	}
 
- }
 
- var FindANSIColor *regexp.Regexp
 
- func init() {
 
- 	FindANSIColor = regexp.MustCompile("\x1b\\[([0-9;]*)m")
 
- }
 
- /*
 
- reading from a closed channel is easy to detect.
 
- res, ok := <-channel
 
- ok == false
 
- writing to a closed channel is a panic.
 
- */
 
- func find_ansicolor(text string) [][]int {
 
- 	var color_codes [][]int
 
- 	// word, _ := regexp.Compile("\x1b\\[([0-9;]+)m")
 
- 	colors := FindANSIColor.FindAllStringIndex(text, -1)
 
- 	// regexp seems to be ignoring the capture groups.
 
- 	// colors := word.FindAllSubmatchIndex([]byte(text), len(text))
 
- 	for _, pos := range colors {
 
- 		txt := text[pos[0]+2 : pos[1]-1]
 
- 		if txt == "" {
 
- 			txt = "0"
 
- 		}
 
- 		// log.Printf("Text: [%s]\n", txt)
 
- 		codes := strings.Split(txt, ";")
 
- 		// log.Printf("Codes: [%#v]\n", codes)
 
- 		code := make([]int, len(codes))
 
- 		for idx, c := range codes {
 
- 			var err error
 
- 			code[idx], err = strconv.Atoi(c)
 
- 			if err != nil {
 
- 				log.Printf("Atoi: %#v [%s]\n", err, c)
 
- 			}
 
- 			color_codes = append(color_codes, code)
 
- 		}
 
- 	}
 
- 	return color_codes
 
- }
 
- type ANSIColorParts struct {
 
- 	Bold  bool
 
- 	Blink bool
 
- 	FG    int
 
- 	BG    int
 
- }
 
- func ParseColorArray(colorarray []int) ANSIColorParts {
 
- 	var acp ANSIColorParts
 
- 	acp.FG = -1
 
- 	acp.BG = -1
 
- 	for _, c := range colorarray {
 
- 		switch c {
 
- 		case 0:
 
- 			acp.FG = 7
 
- 			acp.BG = 0
 
- 		case 1:
 
- 			acp.Bold = true
 
- 		case 5:
 
- 			acp.Blink = true
 
- 		case 30, 31, 32, 33, 34, 35, 36, 37:
 
- 			acp.FG = c - 30
 
- 		case 40, 41, 42, 43, 44, 45, 46, 47:
 
- 			acp.BG = c - 40
 
- 		}
 
- 	}
 
- 	return acp
 
- }
 
- func (d *Door) ParseLastColor(output string) {
 
- 	// use the last color information + whatever is in the string to
 
- 	// track the last color set
 
- 	updated := ParseColorArray(d.LastColor)
 
- 	colors := find_ansicolor(output)
 
- 	for _, codes := range colors {
 
- 		if codes[0] == 0 {
 
- 			updated = ParseColorArray(codes)
 
- 		} else {
 
- 			newCode := ParseColorArray(codes)
 
- 			if newCode.Bold {
 
- 				updated.Bold = true
 
- 			}
 
- 			if newCode.Blink {
 
- 				updated.Blink = true
 
- 			}
 
- 			if (newCode.FG != -1) && (newCode.FG != updated.FG) {
 
- 				updated.FG = newCode.FG
 
- 			}
 
- 			if (newCode.BG != -1) && (newCode.BG != updated.BG) {
 
- 				updated.BG = newCode.BG
 
- 			}
 
- 		}
 
- 	}
 
- 	d.LastColor = make([]int, 1)
 
- 	d.LastColor[0] = 0
 
- 	if updated.Blink {
 
- 		d.LastColor = append(d.LastColor, 5)
 
- 	}
 
- 	if updated.Bold {
 
- 		d.LastColor = append(d.LastColor, 1)
 
- 	}
 
- 	if updated.FG != -1 {
 
- 		d.LastColor = append(d.LastColor, updated.FG+30)
 
- 	}
 
- 	if updated.BG != -1 {
 
- 		d.LastColor = append(d.LastColor, updated.BG+40)
 
- 	}
 
- }
 
- // Write string to client.
 
- func (d *Door) Write(output string) {
 
- 	if d.Disconnected {
 
- 		return
 
- 	}
 
- 	defer func() {
 
- 		if r := recover(); r != nil {
 
- 			log.Println("Write error/HANGUP.")
 
- 			d.Disconnected = true
 
- 		}
 
- 	}()
 
- 	if strings.HasSuffix(output, RestorePos) {
 
- 		output += Color(d.LastColor...)
 
- 	} else {
 
- 		d.ParseLastColor(output)
 
- 	}
 
- 	/*
 
- 		temp := strings.Replace(output, "\x1b", "^[", -1)
 
- 		log.Printf("Parse: [%s]\n", temp)
 
- 	*/
 
- 	writerChannel <- output
 
- 	/*
 
- 		buffer := []byte(output)
 
- 		n, err := syscall.Write(d.WRITEFD, buffer)
 
- 		if err != nil {
 
- 			fmt.Println("Write error/HANGUP?", n)
 
- 			d.Disconnected = true
 
- 		}
 
- 		// No, this isn't it.  The # of bytes in buffer == bytes written.
 
- 		if n != len(buffer) {
 
- 			fmt.Printf("Write fail: %d != %d\n", len(buffer), n)
 
- 		}
 
- 	*/
 
- }
 
 
  |