// makes the menu inside the contacts window func makeContactsMenu(contacts []ts.Contact, contactsWin *gc.Window) ([]*gc.MenuItem, *gc.Menu, *gc.Window) { menu_items := make([]*gc.MenuItem, len(contacts)) var err error for i, val := range contacts { menu_items[i], err = gc.NewItem((val.Name), "") if err != nil { log.Fatal("Error making item for contact menu... ", err) } } contactMenu, err := gc.NewMenu(menu_items) if err != nil { log.Fatal("Error creating contact menu from menu_items... ", err) } contactsWinSizeY, contactsWinSizeX := contactsWin.MaxYX() contactsWin.Keypad(true) contactsMenuWin := contactsWin.Derived((contactsWinSizeY - 5), (contactsWinSizeX - 2), 3, 1) contactMenu.SetWindow(contactsMenuWin) contactMenu.Format(len(contacts), 1) contactMenu.Mark(" * ") title := "Contacts" contactsWin.MovePrint(1, (contactsWinSizeX/2)-(len(title)/2), title) contactsWin.HLine(2, 1, '-', contactsWinSizeX-2) contactsMenuWin.Keypad(true) contactsMenuWin.ScrollOk(true) return menu_items, contactMenu, contactsMenuWin }
//creates the three Main big windows that make up the GUI func createMainWindows(stdscr *gc.Window) (*gc.Window, *gc.Window, *gc.Window, *gc.Window, *gc.Window) { rows, cols := stdscr.MaxYX() height, width := rows, int(float64(cols)*.2) var contactsWin, messageWinBorder, inputBorderWin, inputWin *gc.Window var err error contactsWin, err = gc.NewWindow(height, width, 0, 0) if err != nil { log.Fatal("Failed to create Contact Window:", err) } err = contactsWin.Border('|', '|', '-', '-', '+', '+', '+', '+') if err != nil { log.Fatal("Failed to create Border of Contact Window:", err) } // messageWinBorder is just the border. msgWin is the actual input window // doing this simplifies handling text a fair amount. // also the derived function never errors. Which seems dangerous begin_x := width + 1 height = int(float64(rows) * .8) width = int(float64(cols) * .8) messageWinBorder, err = gc.NewWindow(height, width, 0, begin_x) if err != nil { log.Fatal("Failed to create Message Border Window:", err) } err = messageWinBorder.Border('|', '|', '-', '-', '+', '+', '+', '+') if err != nil { log.Fatal("Failed to create Border of Message Window:", err) } msgWin, err := gc.NewWindow((height - 2), (width - 2), 1, (begin_x + 1)) if err != nil { log.Fatal("Failed to create the message Window:", err) } begin_y := int(float64(rows)*.8) + 1 height = int(float64(rows) * .2) inputBorderWin, err = gc.NewWindow(height, width, begin_y, begin_x) if err != nil { log.Fatal("Failed to create InputBorder Window:", err) } err = inputBorderWin.Border('|', '|', '-', '-', '+', '+', '+', '+') if err != nil { log.Fatal("Failed to create Border of the InputBorder Window:", err) } // inputBorderWin is just the border. InputWin is the actual input window // doing this simplifies handling text a fair amount. // also the derived function never errors. Which seems dangerous inputWin, err = gc.NewWindow((height - 2), (width - 2), (begin_y + 1), (begin_x + 1)) if err != nil { log.Fatal("Failed to create the inputWin Window:", err) } inputWin.ScrollOk(true) inputWin.Keypad(true) msgWin.ScrollOk(true) return contactsWin, messageWinBorder, msgWin, inputBorderWin, inputWin }
// Hello dialog. So the nooblets know the controls func doHello(stdscr *gc.Window) { stdscr.Refresh() y, x := stdscr.MaxYX() center_x := int(x / 2) center_y := int(y / 2) stdscr.MovePrintln(center_y-6, center_x-4, "Controls:") stdscr.MovePrintln(center_y-5, center_x-12, "Escape: Exit the program.") stdscr.MovePrintln(center_y-4, center_x-30, "Tab: Switch between the input window and the Message window.") stdscr.MovePrintln(center_y-3, center_x-11, "Return: Send a message") stdscr.MovePrintln(center_y-2, center_x-44, `Shift + Right Arrow: put in a new line '\n' character (like shift+return in facebook chat)`) stdscr.MovePrintln(center_y-1, center_x-30, "Page-Up / Page-Down: Scroll up in the message history window") }
func handleInput(stdscr *gc.Window, ship *Ship) bool { lines, cols := stdscr.MaxYX() y, x := ship.YX() k := stdscr.GetChar() switch byte(k) { case 0: break case 'a': x-- if x < 2 { x = 2 } case 'd': x++ if x > cols-3 { x = cols - 3 } case 's': y++ if y > lines-4 { y = lines - 4 } case 'w': y-- if y < 2 { y = 2 } case ' ': objects = append(objects, newBullet(y+1, x+4)) objects = append(objects, newBullet(y+3, x+4)) default: return false } ship.MoveWindow(y, x) return true }
func main() { f, err := os.Create("err.log") if err != nil { log.Fatal(err) } defer f.Close() log.SetOutput(f) var stdscr *gc.Window stdscr, err = gc.Init() if err != nil { log.Println("Init:", err) } defer gc.End() rand.Seed(time.Now().Unix()) gc.StartColor() gc.Cursor(0) gc.Echo(false) gc.HalfDelay(1) gc.InitPair(1, gc.C_WHITE, gc.C_BLACK) gc.InitPair(2, gc.C_YELLOW, gc.C_BLACK) gc.InitPair(3, gc.C_MAGENTA, gc.C_BLACK) gc.InitPair(4, gc.C_RED, gc.C_BLACK) gc.InitPair(5, gc.C_BLUE, gc.C_BLACK) gc.InitPair(6, gc.C_GREEN, gc.C_BLACK) lines, cols := stdscr.MaxYX() pl, pc := lines, cols*3 ship := newShip(lines/2, 5) objects = append(objects, ship) field := genStarfield(pl, pc) text := stdscr.Duplicate() c := time.NewTicker(time.Second / 2) c2 := time.NewTicker(time.Second / 16) px := 0 loop: for { text.MovePrintf(0, 0, "Life: [%-5s]", lifeToText(ship.life)) stdscr.Erase() stdscr.Copy(field.Window, 0, px, 0, 0, lines-1, cols-1, true) drawObjects(stdscr) stdscr.Overlay(text) stdscr.Refresh() select { case <-c.C: spawnAsteroid(stdscr.MaxYX()) if px+cols >= pc { break loop } px++ case <-c2.C: updateObjects(stdscr.MaxYX()) drawObjects(stdscr) default: if !handleInput(stdscr, ship) || ship.Expired(-1, -1) { break loop } } } msg := "Game Over" end, err := gc.NewWindow(5, len(msg)+4, (lines/2)-2, (cols-len(msg))/2) if err != nil { log.Fatal("game over:", err) } end.MovePrint(2, 2, msg) end.Box(gc.ACS_VLINE, gc.ACS_HLINE) end.Refresh() gc.Nap(2000) }
// handles keyboard input func inputHandler(inputWin *gc.Window, stdscr *gc.Window, contactsMenuWin *gc.Window, contactMenu *gc.Menu, msgWin *gc.Window) { var NLlocate = map[int]newLine{} var c gc.Char var rawInput gc.Key max_y, max_x := inputWin.MaxYX() for { rawInput = inputWin.GetChar() c = gc.Char(rawInput) // debugLog.Println(rawInput) // debugLog.Println(c) //Escape to Quit if c == gc.Char(27) { break } else if rawInput == gc.KEY_BACKSPACE || c == gc.Char(127) { //Delete Key y, x := inputWin.CursorYX() var del = byte('F') if x != 0 { inputWin.MoveDelChar(y, x-1) del = inputBuffer[placer] copy(inputBuffer[placer:len(inputBuffer)-1], inputBuffer[placer+1:]) inputBuffer = inputBuffer[0 : len(inputBuffer)-1] placer-- if del != byte('\n') && NLlocate[y+scroll]._cursorX > x { temp := newLine{NLlocate[y+scroll]._cursorX - 1, NLlocate[y+scroll]._placer - 1} NLlocate[y+scroll] = temp } //debugLog.Println(inputBuffer) } else if y != 0 { //when x==0 and y!=0 inputWin.Move(y-1, max_x-1) inputWin.MoveDelChar(y-1, max_x-1) del = inputBuffer[placer] copy(inputBuffer[placer:len(inputBuffer)-1], inputBuffer[placer+1:]) inputBuffer = inputBuffer[0 : len(inputBuffer)-1] //debugLog.Println(inputBuffer) placer-- } if del == byte('\n') { inputWin.Erase() inputWin.Print(string(inputBuffer)) inputWin.Move(y-1, NLlocate[y-1+scroll]._cursorX) temp, check := NLlocate[y+scroll] var temp_cursor = temp._cursorX var temp_placer = temp._placer if check && NLlocate[y-1+scroll]._cursorX+temp_cursor >= max_x { _newLine := newLine{NLlocate[y-1+scroll]._cursorX + temp_cursor - max_x, NLlocate[y+scroll]._placer - 1} NLlocate[y+scroll] = _newLine delete(NLlocate, y-1) } else if check { // check if there are any '\n' this line var largest = -1 // if yes, select all '\n' and move for i := range NLlocate { // placer by 1 and adjust cursor if i >= y+scroll { // accordingly if next_nl, ok := NLlocate[i+1]; ok { new_nl := newLine{next_nl._cursorX, next_nl._placer - 1} NLlocate[i] = new_nl } } if i > largest { largest = i } } delete(NLlocate, largest) // delete last map entry _newLine := newLine{NLlocate[y-1+scroll]._cursorX + temp_cursor, NLlocate[y-1+scroll]._placer + temp_placer - 1} NLlocate[y-1+scroll] = _newLine } else { delete(NLlocate, y-1+scroll) } } } else if c == gc.KEY_PAGEDOWN { //debugLog.Println("HIT DOWN") msgWin.Scroll(-10) msgWin.Refresh() inputWin.Refresh() } else if c == gc.KEY_PAGEUP { //debugLog.Println("HIT UP") msgWin.Scroll(10) msgWin.Refresh() inputWin.Refresh() } else if c == gc.KEY_LEFT { y, x := inputWin.CursorYX() if x != 0 { inputWin.Move(y, x-1) placer-- } else if y != 0 { inputWin.Move(y-1, max_x-1) placer-- } if len(inputBuffer) > 0 && inputBuffer[placer+1] == byte('\n') { inputWin.Move(y-1, NLlocate[y-1+scroll]._cursorX) } } else if c == gc.KEY_RIGHT { y, x := inputWin.CursorYX() placer++ if inputBuffer == nil || placer == len(inputBuffer) { inputBuffer = append(inputBuffer, byte(' ')) } if inputBuffer[placer] == byte('\n') || x >= max_x-1 { inputWin.Move(y+1, 0) } else { inputWin.Move(y, x+1) } } else if c == gc.KEY_UP { y, x := inputWin.CursorYX() if y == 0 && placer == 0 { continue } else if y == 0 && scroll > 0 { inputWin.Move(0, x) inputWin.Scroll(-1) scroll -= 1 if NLlocate[y-2+scroll]._placer != 0 { inputWin.Erase() inputWin.Print(string(inputBuffer[(NLlocate[y-2+scroll]._placer):])) } else if placer-max_x-x > 0 { inputWin.Erase() inputWin.Print(string(inputBuffer[(placer - x - max_x):])) } else { inputWin.Erase() inputWin.Print(string(inputBuffer)) } } if y != 0 { inputWin.Move(y-1, x) placer -= max_x if placer < 0 { placer = 0 } } if NLlocate[y-1+scroll]._placer != 0 { if NLlocate[y-1+scroll]._cursorX < x { placer = NLlocate[y-1+scroll]._placer inputWin.Move(y-1, NLlocate[y-1+scroll]._cursorX) } else { placer = NLlocate[y-1+scroll]._placer - (NLlocate[y-1+scroll]._cursorX - x) } } } else if c == gc.KEY_DOWN { y, x := inputWin.CursorYX() if y != max_y { inputWin.Move(y+1, x) if NLlocate[y+scroll]._placer == 0 { placer += max_x } else { placer = NLlocate[y+scroll]._placer + x + 1 } } else if y == max_y { inputWin.Scroll(1) scroll += 1 inputWin.Move(max_y-1, x) if NLlocate[y+scroll]._placer == 0 { placer += max_x } else { placer = NLlocate[y+scroll]._placer + x + 1 } } if placer >= len(inputBuffer) { for i := len(inputBuffer); i < placer+1; i++ { inputBuffer = append(inputBuffer, byte(' ')) } } } else if rawInput == gc.KEY_TAB { y, x := inputWin.CursorYX() gc.Cursor(0) escapeHandler := contactsWindowNavigation(contactsMenuWin, contactMenu) if escapeHandler == 1 { return } gc.Cursor(1) inputWin.Move(y, x) } else if rawInput == gc.KEY_RETURN { placer = -1 for i := range NLlocate { delete(NLlocate, i) } sendMsg(inputWin, globalMsgWin) } else if rawInput == gc.KEY_SRIGHT { y, x := inputWin.CursorYX() if inputBuffer == nil || placer == len(inputBuffer)-1 { if y == max_y-1 { scroll++ } inputWin.Print("\n") temp := newLine{x, placer} NLlocate[y+scroll] = temp placer++ inputBuffer = append(inputBuffer, byte('\n')) } else { inputWin.Erase() inputBuffer = append(inputBuffer, byte('\n')) copy(inputBuffer[placer+1:], inputBuffer[placer:]) inputBuffer[placer+1] = byte('\n') inputWin.Print(string(inputBuffer)) temp := newLine{x, placer} placer++ nextholder, check := NLlocate[y+1+scroll] if check { for i := range NLlocate { if i == y+scroll { _newLine := newLine{NLlocate[i]._cursorX + 1 - x, NLlocate[i]._placer + 1} nextholder := NLlocate[i+1] _ = nextholder NLlocate[i+1] = _newLine } else if i > y { temp := NLlocate[i+1] NLlocate[i+1] = nextholder nextholder = temp } } } NLlocate[y+scroll] = temp inputWin.Move(y+1, 0) } } else if rawInput == gc.KEY_SLEFT { } else { y, x := inputWin.CursorYX() if inputBuffer == nil || placer == len(inputBuffer)-1 { inputWin.Print(string(c)) inputBuffer = append(inputBuffer, byte(c)) } else { inputWin.Erase() inputBuffer = append(inputBuffer, byte(c)) copy(inputBuffer[placer+1:], inputBuffer[placer:]) inputBuffer[placer+1] = byte(c) inputWin.Print(string(inputBuffer)) for i := range NLlocate { if i > y+scroll { tempLine := newLine{NLlocate[i]._cursorX, NLlocate[i]._placer + 1} NLlocate[i] = tempLine } } if NLlocate[y+scroll]._cursorX >= x { if NLlocate[y+scroll]._cursorX == max_x { copy(inputBuffer[NLlocate[y+scroll]._placer:len(inputBuffer)-1], inputBuffer[NLlocate[y+scroll]._placer+1:]) inputBuffer = inputBuffer[0 : len(inputBuffer)-1] delete(NLlocate, y) } else { temp := newLine{NLlocate[y+scroll]._cursorX + 1, NLlocate[y+scroll]._placer + 1} NLlocate[y+scroll] = temp } } } placer++ inputWin.Move(y, x+1) } } }