func main() { // Handle options help := flag.Bool("help", false, "Show usage") verbose := flag.Bool("verbose", false, "Verbose output") fullscreen := flag.Bool("fullscreen", false, "Go fullscreen!") bgImage := flag.String("bg-image", "", "Background image file") flag.Usage = func() { fmt.Fprintf(os.Stderr, "shell - A system shell based on CLIngon (Command Line INterface for Go Nerds\n\n") fmt.Fprintf(os.Stderr, "Usage:\n\n") fmt.Fprintf(os.Stderr, "\tshell [options] <fontfile> \n\n") fmt.Fprintf(os.Stderr, "Options are:\n\n") flag.PrintDefaults() } flag.Parse() if *help == true { flag.Usage() return } if len(flag.Args()) < 1 { flag.Usage() return } config := configuration{ verbose: *verbose, fullscreen: *fullscreen, bgImage: *bgImage, consoleX: 40, consoleY: 40, consoleW: 560, consoleH: 400, animationLength: ANIMATION_LENGTH, } r := initialize(&config) y_channel := make(chan int16) running := true // Have to start this *before* printing to the console, // because the printing will cause some messages to be sent to 'sdlrenderer.UpdatedRectsCh()' go func() { var y int16 = config.consoleY for running { select { case newY := <-y_channel: y = newY r.render(nil, y) case rects := <-sdlrenderer.UpdatedRectsCh(): r.render(rects, y) } } }() var console *clingon.Console = clingon.NewConsole(&ShellEvaluator{}) console.SetRenderer(r.sdlRenderer) y_channel <- config.consoleY console.Print(greetingText) console.SetPrompt("shell:$ ") var anim *clingon.Animation = nil var animValueCh <-chan float64 = nil toggleAnimation := false for running { select { case event := <-sdl.Events: switch e := event.(type) { case sdl.QuitEvent: running = false case sdl.MouseMotionEvent: var y int state := sdl.GetRelativeMouseState(nil, &y) if state == 1 { if y < 0 { sdlrenderer.EventCh() <- clingon.Cmd_Scroll{clingon.SCROLL_UP} } else if y > 0 { sdlrenderer.EventCh() <- clingon.Cmd_Scroll{clingon.SCROLL_DOWN} } } case sdl.KeyboardEvent: keyName := sdl.GetKeyName(sdl.Key(e.Keysym.Sym)) if config.verbose { fmt.Printf("\n") fmt.Printf("%v: %v", e.Keysym.Sym, ": ", keyName) fmt.Printf("%04x ", e.Type) for i := 0; i < len(e.Pad0); i++ { fmt.Printf("%02x ", e.Pad0[i]) } fmt.Printf("\n") fmt.Printf("Type: %02x Which: %02x State: %02x Pad: %02x\n", e.Type, e.Which, e.State, e.Pad0[0]) fmt.Printf("Scancode: %02x Sym: %08x Mod: %04x Unicode: %04x\n", e.Keysym.Scancode, e.Keysym.Sym, e.Keysym.Mod, e.Keysym.Unicode) } if (keyName == "escape") && (e.Type == sdl.KEYDOWN) { running = false } else if (keyName == "f10") && (e.Type == sdl.KEYDOWN) { if anim != nil { anim.Terminate() <-anim.FinishedCh() anim = nil } toggleAnimation = !toggleAnimation slidingDistance := int16(r.appSurface.H) - config.consoleY anim = clingon.NewSliderAnimation(config.animationLength, float64(slidingDistance)) animValueCh = anim.ValueCh() anim.Start() } else if (keyName == "page up") && (e.Type == sdl.KEYDOWN) { sdlrenderer.EventCh() <- clingon.Cmd_Scroll{clingon.SCROLL_UP} } else if (keyName == "page down") && (e.Type == sdl.KEYDOWN) { sdlrenderer.EventCh() <- clingon.Cmd_Scroll{clingon.SCROLL_DOWN} } else if (keyName == "up") && (e.Type == sdl.KEYDOWN) { console.PutReadline(clingon.HISTORY_PREV) } else if (keyName == "down") && (e.Type == sdl.KEYDOWN) { console.PutReadline(clingon.HISTORY_NEXT) } else if (keyName == "left") && (e.Type == sdl.KEYDOWN) { console.PutReadline(clingon.CURSOR_LEFT) } else if (keyName == "right") && (e.Type == sdl.KEYDOWN) { console.PutReadline(clingon.CURSOR_RIGHT) } else { unicode := e.Keysym.Unicode if unicode > 0 { console.PutUnicode(unicode) } } } case value := <-animValueCh: var y float64 if toggleAnimation { y = 40 + value } else { y = float64(r.appSurface.H) - value } y_channel <- int16(y) } } // End of "for running" sdl.Quit() }
func (r *SDLRenderer) loop() { var slider_orNil *clingon.Animation = nil var sliderTargetState int = -1 var sliderValueCh_orNil <-chan float64 = nil var sliderFinishedCh_orNil <-chan bool = nil evtLoop := r.app.NewEventLoop() shutdown.Add(1) for { select { case <-evtLoop.Pause: if slider_orNil != nil { slider_orNil.Terminate() <-sliderFinishedCh_orNil slider_orNil = nil sliderTargetState = -1 sliderValueCh_orNil = nil sliderFinishedCh_orNil = nil } r.destroyCliRenderer() evtLoop.Pause <- 0 case <-evtLoop.Terminate: // Terminate this Go routine if r.app.Verbose { r.app.PrintfMsg("frontend SDL renderer event loop: exit") } evtLoop.Terminate <- 0 shutdown.Done() return case cmd := <-r.sliderCh: slider_orNil = cmd.anim sliderTargetState = cmd.targetState sliderValueCh_orNil = cmd.anim.ValueCh() sliderFinishedCh_orNil = cmd.anim.FinishedCh() case value := <-sliderValueCh_orNil: if sliderTargetState == HIDE { r.consoleY = int16(float64(r.height/2) + value*float64(r.height/2)) } else { r.consoleY = int16(float64(r.height) - value*float64(r.height/2)) } composer.SetPosition(r.cliSurface_orNil.GetSurface(), 0, int(r.consoleY)) case <-sliderFinishedCh_orNil: if sliderTargetState == HIDE { r.destroyCliRenderer() } slider_orNil = nil sliderTargetState = -1 sliderValueCh_orNil = nil sliderFinishedCh_orNil = nil r.toggling = false case cmd := <-r.cliSurfaceCh: r.destroyCliRenderer() r.cliSurface_orNil = cmd.surface_orNil cli.SetRenderer(cmd.surface_orNil) if r.cliSurface_orNil != nil { composer.AddInputSurface(r.cliSurface_orNil.GetSurface(), 0, int(r.consoleY), r.cliSurface_orNil.UpdatedRectsCh()) } cmd.done <- true case cmd := <-r.speccySurfaceCh: <-composer.RemoveAllInputSurfaces() r.speccySurface.GetSurface().Free() r.speccySurface = cmd.surface composer.AddInputSurface(r.speccySurface.GetSurface(), 0, 0, r.speccySurface.UpdatedRectsCh()) if r.cliSurface_orNil != nil { composer.AddInputSurface(r.cliSurface_orNil.GetSurface(), 0, int(r.consoleY), r.cliSurface_orNil.UpdatedRectsCh()) } cmd.done <- true case cmd := <-r.appSurfaceCh: <-composer.ReplaceOutputSurface(nil) r.appSurface.GetSurface().Free() r.appSurface = cmd.surface <-composer.ReplaceOutputSurface(r.appSurface.GetSurface()) cmd.done <- true } } }