package main import "fmt" import "math" import "git.tebibyte.media/sashakoshka/stone" func clear (x, y, width, height int) { for yy := 0; yy < height; yy ++ { for xx := 0; xx < width; xx ++ { application.SetRune(xx + x, yy + y, 0) application.SetColor(xx + x, yy + y, stone.ColorForeground) }} } func fillColor (x, y, width, height int, color stone.Color) { for yy := 0; yy < height; yy ++ { for xx := 0; xx < width; xx ++ { application.SetColor(xx + x, yy + y, color) }} } func redraw () { width, _ := application.Size() showLeftColumn = width > 44 if showLeftColumn { drawNumberReadouts() } drawInput() } func drawInput () { width, height := application.Size() xOffset := 0 if showLeftColumn { xOffset = 26 } y := height - 1 inputWidth, _ := inputBuffer.Size() newWidth := width - xOffset if newWidth != inputWidth { inputBuffer.SetSize(newWidth, 1) } inputBuffer.Clear() if expressionRoot != nil { expressionRoot.Render(&inputBuffer, 0) } for x := 0; x < newWidth; x ++ { character := '_' cell := inputBuffer.Cell(x, 0) if cell.Rune() > 0 { character = cell.Rune() } application.SetRune(x + xOffset, y, character) if character == '_' { application.SetColor(x + xOffset, y, stone.ColorDim) application.SetStyle(x + xOffset, y, stone.StyleNormal) } else { application.SetColor(x + xOffset, y, cell.Color()) application.SetStyle(x + xOffset, y, cell.Style()) } } } func drawNumberReadouts () { _, height := application.Size() indicatorY := height - 12 application.SetDot(0, indicatorY) fmt.Fprint(application, "sel fin | int float") fillColor(0, indicatorY, 19, 1, stone.ColorDim) if showEndResult { fillColor(4, indicatorY, 3, 1, stone.ColorBlue) } else { fillColor(0, indicatorY, 3, 1, stone.ColorBlue) } clear(0, height - 10, 25, 10) if showFloat { fillColor(14, indicatorY, 5, 1, stone.ColorBlue) drawNumberReadoutsFloat() } else { fillColor(10, indicatorY, 3, 1, stone.ColorBlue) drawNumberReadoutsInt() } } func drawNumberReadoutsInt () { _, height := application.Size() var number int64 var err error if showEndResult { if expressionRoot != nil { number, err = expressionRoot.Solution() } } else { if selectedExpression != nil { number, err = selectedExpression.Solution() } } if err != nil { application.SetDot((25 - len(err.Error())) / 2, height - 6) fmt.Fprint(application, err.Error()) } else { drawHexadecimal (0, height - 10, uint64(number)) drawDecimal (0, height - 8, uint64(number)) drawOctal (0, height - 6, uint64(number)) drawBinary (0, height - 4, uint64(number)) } } func drawNumberReadoutsFloat () { _, height := application.Size() var number float64 var err error if showEndResult { if expressionRoot != nil { number, err = expressionRoot.InexactSolution() } } else { if selectedExpression != nil { number, err = selectedExpression.InexactSolution() } } if err != nil { application.SetDot((25 - len(err.Error())) / 2, height - 6) fmt.Fprint(application, err.Error()) } else { firstHalf := int64(math.Floor(number)) secondHalf := (number - math.Floor(number)) application.SetDot(0, height - 7) fmt.Fprint(application, "10") application.SetColor(0, height - 7, stone.ColorBlue) application.SetColor(1, height - 7, stone.ColorBlue) application.SetDot(3, height - 7) fmt.Fprintf(application, "%+d", firstHalf) application.SetRune(3, height - 6, '.') for index := 4; index < 25; index ++ { secondHalf *= 10 secondHalf = math.Mod(secondHalf, 10) digit := rune(secondHalf) + '0' application.SetRune(index, height - 6, digit) } drawBinary(0, height - 4, math.Float64bits(number)) if math.Signbit(number) { application.SetColor(3, height - 7, stone.ColorRed) } else { application.SetColor(3, height - 7, stone.ColorGreen) } } } func drawBinary (xOffset, yOffset int, number uint64) { bitOffset := 64 for y := 0; y < 4; y ++ { application.SetDot(xOffset, y + yOffset) fmt.Fprint(application, bitOffset) application.SetColor(xOffset, y + yOffset, stone.ColorBlue) application.SetColor(xOffset + 1, y + yOffset, stone.ColorBlue) for x := 0; x < 16; x ++ { bitOffset -- trueX := x + xOffset + x / 4 + 3 character := '0' + rune((number >> bitOffset) & 0x1) application.SetRune(trueX, y + yOffset, character) if character == '0' { application.SetColor ( trueX, y + yOffset, stone.ColorDim) } else { application.SetColor ( trueX, y + yOffset, stone.ColorForeground) } } application.SetDot(xOffset + 23, y + yOffset) fmt.Fprint(application, bitOffset + 1) application.SetColor(xOffset + 23, y + yOffset, stone.ColorBlue) application.SetColor(xOffset + 24, y + yOffset, stone.ColorBlue) } } func drawHexadecimal (xOffset, yOffset int, number uint64) { bitOffset := 64 application.SetDot(xOffset, yOffset) fmt.Fprint(application, "16") application.SetColor(xOffset, yOffset, stone.ColorBlue) application.SetColor(xOffset + 1, yOffset, stone.ColorBlue) number = drawSign(xOffset, yOffset, number) for x := 0; x < 16; x ++ { bitOffset -= 4 trueX := x + xOffset + x / 4 + 6 character := rune((number >> bitOffset) & 0xF) if character < 10 { character += '0' } else { character += 'A' - 10 } application.SetRune(trueX, yOffset, character) if character == '0' { application.SetColor ( trueX, yOffset, stone.ColorDim) } else { application.SetColor ( trueX, yOffset, stone.ColorForeground) } } } func drawDecimal (xOffset, yOffset int, number uint64) { var divisor uint64 = 10000000000000000000 application.SetDot(xOffset, yOffset) fmt.Fprint(application, "10") application.SetColor(xOffset, yOffset, stone.ColorBlue) application.SetColor(xOffset + 1, yOffset, stone.ColorBlue) number = drawSign(xOffset, yOffset, number) for x := 0; x < 20; x ++ { trueX := x + xOffset + 5 character := rune((number / divisor) % 10) + '0' application.SetRune(trueX, yOffset, character) if character == '0' { application.SetColor ( trueX, yOffset, stone.ColorDim) } else { application.SetColor ( trueX, yOffset, stone.ColorForeground) } divisor /= 10 } } func drawOctal (xOffset, yOffset int, number uint64) { // fuck octal i hate it almost as much as decimal bitOffset := 63 application.SetDot(xOffset, yOffset) fmt.Fprint(application, "08") application.SetColor(xOffset, yOffset, stone.ColorBlue) application.SetColor(xOffset + 1, yOffset, stone.ColorBlue) number = drawSign(xOffset, yOffset, number) for x := 0; x < 21; x ++ { bitOffset -= 3 trueX := x + xOffset + 4 character := '0' + rune((number >> bitOffset) % 8) application.SetRune(trueX, yOffset, character) if character == '0' { application.SetColor ( trueX, yOffset, stone.ColorDim) } else { application.SetColor ( trueX, yOffset, stone.ColorForeground) } } } func drawSign (xOffset, yOffset int, number uint64) (alteredNumber uint64) { alteredNumber = number if showSigned { if int64(alteredNumber) >= 0 { application.SetRune(xOffset + 3, yOffset, '+') application.SetColor ( xOffset + 3, yOffset, stone.ColorGreen) } else { application.SetRune(xOffset + 3, yOffset, '-') application.SetColor ( xOffset + 3, yOffset, stone.ColorRed) alteredNumber = uint64(int64(number) * -1) } } return }