# Testable primitives for writing to screen. # # Mu mostly uses the screen for text, but it builds it out of pixel graphics # and a bitmap font. There is no support for a blinking cursor, scrolling and # so on. # # Fake screens are primarily for testing text-mode prints. However, they do # support some rudimentary pixel operations as well. Caveats: # # - Drawing pixels atop text or vice versa is not supported. Results in a fake # screen will not mimic real screens in these situations. # - Fake screens currently also assume a fixed-width 8x16 font. type screen { # text mode width: int height: int data: (handle array screen-cell) cursor-x: int # [0..width) cursor-y: int # [0..height) # pixel graphics pixels: (handle array byte) } type screen-cell { data: grapheme color: int background-color: int } fn initialize-screen _screen: (addr screen), width: int, height: int, pixel-graphics?: boolean { var screen/esi: (addr screen) <- copy _screen var tmp/eax: int <- copy 0 var dest/edi: (addr int) <- copy 0 # screen->width = width dest <- get screen, width tmp <- copy width copy-to *dest, tmp # screen->height = height dest <- get screen, height tmp <- copy height copy-to *dest, tmp # populate screen->data { var data-ah/edi: (addr handle array screen-cell) <- get screen, data var capacity/eax: int <- copy width capacity <- multiply height populate data-ah, capacity } # if necessary, populate screen->pixels { compare pixel-graphics?, 0/false break-if-= var pixels-ah/edi: (addr handle array byte) <- get screen, pixels var capacity/eax: int <- copy width capacity <- shift-left 3/log2-font-width capacity <- multiply height capacity <- shift-left 4/log2-font-height populate pixels-ah, capacity } # screen->cursor-x = 0 dest <- get screen, cursor-x copy-to *dest, 0 # screen->cursor-y = 0 dest <- get screen, cursor-y copy-to *dest, 0 } # in graphemes fn screen-size _screen: (addr screen) -> _/eax: int, _/ecx: int { var screen/esi: (addr screen) <- copy _screen var width/eax: int <- copy 0 var height/ecx: int <- copy 0 compare screen, 0 { break-if-!= return 0x80/128, 0x30/48 } # fake screen var tmp/edx: (addr int) <- get screen, width width <- copy *tmp tmp <- get screen, height height <- copy *tmp return width, height } # testable screen primitive fn draw-grapheme _screen: (addr screen), g: grapheme, x: int, y: int, color: int, background-color: int { var screen/esi: (addr screen) <- copy _screen { compare screen, 0 break-if-!= draw-grapheme-on-real-screen g, x, y, color, background-color return } # fake screen var idx/ecx: int <- screen-cell-index screen, x, y var data-ah/eax: (addr handle array screen-cell) <- get screen, data var data/eax: (addr array screen-cell) <- lookup *data-ah var offset/ecx: (offset screen-cell) <- compute-offset data, idx var dest-cell/ecx: (addr screen-cell) <- index data, offset var dest-grapheme/eax: (addr grapheme) <- get dest-cell, data var g2/edx: grapheme <- copy g copy-to *dest-grapheme, g2 var dest-color/eax: (addr int) <- get dest-cell, color var src-color/edx: int <- copy color copy-to *dest-color, src-color dest-color <- get dest-cell, background-color src-color <- copy background-color copy-to *dest-color, src-color } # we can't really render non-ASCII yet, but when we do we'll be ready fn draw-code-point screen: (addr screen), c: code-point, x: int, y: int, color: int, background-color: int { var g/eax: grapheme <- copy c draw-grapheme screen, g, x, y, color, background-color } # not really needed for a real screen, though it shouldn't do any harm fn screen-cell-index _screen: (addr screen), x: int, y: int -> _/ecx: int { var screen/esi: (addr s
// +build darwin

package background

import (
	"fmt"
	"os/exec"
	"strconv"
)

// SetFromFile takes a string as an input, it must be absolute path to
// the background. Checks are not made to check if the path exists or
// it is actually an image, that must be verified before passing it to
// SetFromFile. SetFromFile will exit returning in error if there is
// any.
func SetFromFile(path string) error {
	err := exec.Command("osascript", "-e",
		`tell application "System Events" to tell every desktop to set picture to `+strconv.Quote(path)).Run()
	if err != nil {
		err = fmt.Errorf("%s\n%s",
			"set_darwin.go: failed to set background",
			err.Error())
	}
	return err
}
t -> _/eax: int { var screen/esi: (addr screen) <- copy _screen var data-ah/eax: (addr handle array screen-cell) <- get screen, data var data/eax: (addr array screen-cell) <- lookup *data-ah var idx/ecx: int <- copy idx-on-stack var offset/ecx: (offset screen-cell) <- compute-offset data, idx var cell/eax: (addr screen-cell) <- index data, offset var src/eax: (addr int) <- get cell, background-color var result/eax: int <- copy *src return result } fn pixel screen: (addr screen), x: int, y: int, color: int { { compare screen, 0 break-if-!= pixel-on-real-screen x, y, color return } # fake screen var screen/esi: (addr screen) <- copy screen var pixels-ah/eax: (addr handle array byte) <- get screen, pixels var pixels/eax: (addr array byte) <- lookup *pixels-ah { compare pixels, 0 break-if-!= abort "pixel graphics not enabled for this screen" } var idx/ecx: int <- pixel-index screen, x, y var dest/ecx: (addr byte) <- index pixels, idx var src/eax: byte <- copy-byte color copy-byte-to *dest, src } fn pixel-index _screen: (addr screen), x: int, y: int -> _/ecx: int { var screen/esi: (addr screen) <- copy _screen { compare x, 0 break-if->= abort "screen-cell-index: negative x" } { var xmax-a/eax: (addr int) <- get screen, width var xmax/eax: int <- copy *xmax-a xmax <- shift-left 3/log2-font-width compare x, xmax break-if-< abort "screen-cell-index: x too high" } { compare y, 0 break-if->= abort "screen-cell-index: negative y" } { var ymax-a/eax: (addr int) <- get screen, height var ymax/eax: int <- copy *ymax-a ymax <- shift-left 4/log2-font-height compare y, ymax break-if-< abort "screen-cell-index: y too high" } var width-addr/eax: (addr int) <- get screen, width var result/ecx: int <- copy y result <- multiply *width-addr result <- shift-left 3/log2-font-width result <- add x return result }