testdoor.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "red-green/door"
  6. "runtime/debug"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "github.com/mitchellh/go-wordwrap"
  11. )
  12. func pctUpdate(pct *int64) func() int64 {
  13. return func() int64 {
  14. return *pct
  15. }
  16. }
  17. // Can I add a function to Door?
  18. // NO: cannot define new methods on non-local type door.Door
  19. /*
  20. func (d *door.Door) PressAKey() {
  21. d.Write(door.Reset + door.CRNL + "Press a key to continue...")
  22. d.Key()
  23. d.Write(door.CRNL)
  24. }
  25. */
  26. func press_keys(d *door.Door) {
  27. d.Write(door.Reset + door.CRNL + "Press some keys...")
  28. var k int
  29. for k != 0x0d {
  30. k = d.Key()
  31. if k == door.XKEY_MOUSE {
  32. var m door.MouseInfo = door.Mouse
  33. d.Write(fmt.Sprintf("M %d (%d,%d) ", m.Button, m.X, m.Y))
  34. } else {
  35. d.Write(fmt.Sprintf("%d (%x) ", k, k))
  36. }
  37. }
  38. d.Write(door.Reset + door.CRNL)
  39. }
  40. func press_a_key(d *door.Door) int {
  41. d.Write(door.Reset + door.CRNL + "Press a key to continue...")
  42. var k int = d.Key()
  43. d.Write(door.CRNL)
  44. return k
  45. }
  46. func about_test_door(d *door.Door) {
  47. var W int = 60
  48. var center_x int = (door.Width - W) / 2
  49. var center_y int = (door.Height - 16) / 2
  50. var about door.Panel = door.Panel{X: center_x,
  51. Y: center_y,
  52. Width: W,
  53. Style: door.SINGLE_DOUBLE,
  54. BorderColor: door.ColorText("BOLD YELLOW ON BLUE"),
  55. }
  56. about.Lines = append(about.Lines, door.Line{Text: fmt.Sprintf("%*s", -W, "About This Door"),
  57. DefaultColor: door.ColorText("BOLD CYAN ON BLUE")})
  58. about.Lines = append(about.Lines, about.Spacer())
  59. about.Lines = append(about.Lines, door.Line{Text: fmt.Sprintf("%*s", -W, "Test Door written in go, using go door.")})
  60. var copyright string = "(C) 2022 Bugz, Red Green Software"
  61. if door.Unicode {
  62. copyright = strings.Replace(copyright, "(C)", "\u00a9", -1)
  63. }
  64. about.Lines = append(about.Lines,
  65. door.Line{Text: copyright, Width: W,
  66. DefaultColor: door.ColorText("BOLD WHITE ON BLUE")})
  67. for _, text := range []string{"",
  68. "This door was written by Bugz.",
  69. "",
  70. "It is written in Go, understands CP437 and unicode, adapts",
  71. "to screen sizes, uses door32.sys, supports TheDraw Fonts",
  72. "(the fonts are compiled into the door), has NoMoreSecrets",
  73. "effect, and runs on Linux and Windows."} {
  74. about.Lines = append(about.Lines, door.Line{Text: text, Width: W})
  75. }
  76. var better door.NoMoreSecretsConfig = door.NoMoreSecretsDefault
  77. better.Jumble_Loop_Speed = 75 // 35
  78. better.Reveal_Loop_Speed = 100 // 50
  79. better.Color = door.ColorText("BRI CYAN ON BLUE")
  80. door.NoMoreSecrets(about.Output(), d, &better)
  81. }
  82. func MainMenu() door.Menu {
  83. // Make the main menu
  84. var menu door.Menu = door.Menu{Panel: door.Panel{Width: 45,
  85. X: 2,
  86. Y: 5,
  87. Style: door.DOUBLE,
  88. Title: "[ Main Menu: ]",
  89. TitleOffset: 3,
  90. BorderColor: door.ColorText("BRI CYAN ON BLA")}}
  91. menu.SelectedR = door.MakeMenuRender(door.ColorText("BOLD CYAN"),
  92. door.ColorText("BOLD BLUE"),
  93. door.ColorText("BOLD WHITE"),
  94. door.ColorText("BOLD CYAN"))
  95. menu.UnselectedR = door.MakeMenuRender(door.ColorText("BOLD YEL ON BLUE"),
  96. door.ColorText("BOLD WHI ON BLUE"),
  97. door.ColorText("BOLD YEL ON BLUE"),
  98. door.ColorText("BOLD CYAN ON BLUE"))
  99. menu.AddSelection("A", "ANSI Display")
  100. // m.AddSelection("C", "Crash")
  101. menu.AddSelection("D", "Display Information (dropfile, screen)")
  102. menu.AddSelection("F", "Font Demo")
  103. menu.AddSelection("I", "Input Prompt Demo")
  104. menu.AddSelection("M", "Menu Demo")
  105. menu.AddSelection("P", "Progress Bars Demo")
  106. menu.AddSelection("S", "Show Panel")
  107. menu.AddSelection("T", "Test Door About")
  108. menu.AddSelection("W", "Screen Width")
  109. menu.AddSelection("Q", "Quit")
  110. var descriptions []string = []string{
  111. // 12345678901234567890123456789012345678901234567890
  112. "Display an ANSI file. It is compiled into the door itself.",
  113. // "Crash go, see a handled error.", // The error shows up in the logs.
  114. "Display dropfile information.",
  115. "Display TheDraw Fonts. Font information is compiled into the door.",
  116. "Input some values, while updating the time.",
  117. "Isn't this is a menu?",
  118. "Display various progress bar styles. Half step, display percentage, and gradient.",
  119. "Show multiple panels.",
  120. "Show more information about the door, using NoMoreSecrets effect.",
  121. "Examples using the full width of the screen.",
  122. "Exit this door.",
  123. }
  124. var widthLeft int = door.Width - (menu.Width + menu.X + 2)
  125. var panelWidth int = widthLeft - (2 + 2)
  126. var maxLines int = 1
  127. var maxLineLength int
  128. // Calculate the max lines needed for each line.
  129. for _, line := range descriptions {
  130. var wrapped string = wordwrap.WrapString(line, uint(panelWidth))
  131. var lines int = len(strings.Split(wrapped, "\n"))
  132. if lines > maxLines {
  133. maxLines = lines
  134. }
  135. if len(line) > maxLineLength {
  136. maxLineLength = len(line)
  137. }
  138. }
  139. if maxLines == 1 {
  140. // Ok! Everything fits into one line, SO use max line length as width of panel.
  141. panelWidth = maxLineLength
  142. }
  143. // Position the description panel beside the menu. m.Width + m.X + 2 (1 one to give it a space)
  144. var descPanel door.Panel = door.Panel{X: menu.Width + menu.X + 2 + 1, Y: menu.Y, Width: panelWidth, Style: door.SINGLE, BorderColor: door.ColorText("WHI ON BLU")}
  145. for x := 0; x < maxLines; x++ {
  146. descPanel.Lines = append(descPanel.Lines, door.Line{Text: "", Width: panelWidth})
  147. }
  148. menu.Activated = func(item int, d *door.Door) {
  149. var line string = descriptions[item]
  150. var lines []string = strings.Split(wordwrap.WrapString(line, uint(panelWidth)), "\n")
  151. for idx, _ := range descPanel.Lines {
  152. if idx >= len(lines) {
  153. descPanel.Lines[idx].Text = ""
  154. } else {
  155. descPanel.Lines[idx].Text = lines[idx]
  156. }
  157. }
  158. d.Write(door.SavePos + descPanel.Output() + door.RestorePos)
  159. }
  160. return menu
  161. }
  162. func display_information(d *door.Door) {
  163. d.Write(door.Clrscr + door.CRNL)
  164. var keyColor string = door.ColorText("BRI GREEN")
  165. var sepColor string = door.ColorText("BRI YEL")
  166. var valColor string = door.ColorText("CYAN")
  167. var nice_format func(string, string) string = func(key string, value string) string {
  168. return fmt.Sprintf("%s%-20s %s: %s%s", keyColor, key, sepColor, valColor, value) + door.CRNL
  169. }
  170. d.Write(nice_format("BBS Software", d.Config.BBSID))
  171. d.Write(nice_format("Time Left", strconv.Itoa(d.Config.Time_left)))
  172. d.Write(nice_format("Real Name", d.Config.Real_name))
  173. d.Write(nice_format("Comm Type", strconv.Itoa(d.Config.Comm_type)))
  174. d.Write(nice_format("Comm Handle", strconv.Itoa(d.Config.Comm_handle)))
  175. d.Write(nice_format("Baudrate", strconv.Itoa(d.Config.Baudrate)))
  176. d.Write(nice_format("Handle", d.Config.Handle))
  177. d.Write(nice_format("User #", strconv.Itoa(d.Config.User_number)))
  178. d.Write(nice_format("Security Level", strconv.Itoa(d.Config.Security_level)))
  179. d.Write(nice_format("Node #", strconv.Itoa(d.Config.Node)))
  180. d.Write(nice_format("Emulation", strconv.Itoa(d.Config.Emulation)))
  181. d.Write(nice_format("Unicode", strconv.FormatBool(door.Unicode)))
  182. d.Write(nice_format("CP437", strconv.FormatBool(door.CP437)))
  183. d.Write(nice_format("Full CP437", strconv.FormatBool(door.Full_CP437)))
  184. d.Write(nice_format("Screen Size", fmt.Sprintf("%d X %d", door.Width, door.Height)))
  185. }
  186. func display_ansi(d *door.Door) {
  187. var art []string = ANSIGrowl()
  188. d.Write(door.Clrscr)
  189. for _, line := range art {
  190. d.Write(line + door.CRNL)
  191. }
  192. }
  193. func font_demo(d *door.Door) {
  194. var output []string
  195. var l int
  196. var centering string
  197. d.Write(door.Clrscr + door.CRNL) // + door.CRNL + door.CRNL)
  198. var fac door.ColorFont = FontAmazonCyan()
  199. output, l = fac.Output("ABCDEFGHIJKL")
  200. if l > door.Width {
  201. output, l = fac.Output("Cyan")
  202. }
  203. if l < door.Width {
  204. centering = strings.Repeat(" ", (door.Width-l)/2)
  205. for _, o := range output {
  206. d.Write(fmt.Sprintf("%s%s%s", centering, o, door.Reset) + door.CRNL)
  207. }
  208. d.Write(door.CRNL)
  209. }
  210. var patch door.ColorMap = fac.Scan(6)
  211. // log.Printf("Patch: %#v\n", patch)
  212. fac.Modify(4, patch)
  213. output, l = fac.Output("Blue")
  214. centering = strings.Repeat(" ", (door.Width-l)/2)
  215. for _, o := range output {
  216. d.Write(fmt.Sprintf("%s%s%s", centering, o, door.Reset) + door.CRNL)
  217. }
  218. d.Write(door.CRNL)
  219. fac.Modify(1, patch)
  220. output, l = fac.Output("Red")
  221. centering = strings.Repeat(" ", (door.Width-l)/2)
  222. for _, o := range output {
  223. d.Write(fmt.Sprintf("%s%s%s", centering, o, door.Reset) + door.CRNL)
  224. }
  225. d.Write(door.CRNL)
  226. press_a_key(d)
  227. var fab door.ColorFont = FontAnarchyBlue()
  228. output, l = fab.Output("Bugz is Here!")
  229. if l > door.Width {
  230. output, l = fab.Output("Hello")
  231. }
  232. if l < door.Width {
  233. centering = strings.Repeat(" ", (door.Width-l)/2)
  234. for _, o := range output {
  235. d.Write(centering + o + door.Reset + door.CRNL)
  236. }
  237. d.Write(door.CRNL)
  238. }
  239. var unchain door.ColorFont = FontUnchained()
  240. output, l = unchain.Output("Hi There!")
  241. if l > door.Width {
  242. output, l = unchain.Output("Meow")
  243. }
  244. if l < door.Width {
  245. centering = strings.Repeat(" ", (door.Width-l)/2)
  246. for _, o := range output {
  247. d.Write(centering + o + door.Reset + door.CRNL)
  248. }
  249. d.Write(door.CRNL)
  250. }
  251. press_a_key(d)
  252. var asylum door.ColorFont = FontAsylum()
  253. output, l = asylum.Output("Bugz ROCKS")
  254. if l > door.Width {
  255. output, l = asylum.Output("Aslym")
  256. }
  257. if l < door.Width {
  258. centering = strings.Repeat(" ", (door.Width-l)/2)
  259. for _, o := range output {
  260. d.Write(centering + o + door.Reset + door.CRNL)
  261. }
  262. d.Write(door.CRNL)
  263. }
  264. var brain door.ColorFont = FontBrainDmgBlu()
  265. output, l = brain.Output("I'm so BLUE")
  266. if l > door.Width {
  267. output, l = brain.Output("Blue")
  268. }
  269. if l < door.Width {
  270. centering = strings.Repeat(" ", (door.Width-l)/2)
  271. for _, o := range output {
  272. d.Write(centering + o + door.Reset + door.CRNL)
  273. }
  274. d.Write(door.CRNL)
  275. }
  276. var boner door.ColorFont = FontBoner()
  277. output, l = boner.Output("Welcome!")
  278. if l < door.Width {
  279. centering = strings.Repeat(" ", (door.Width-l)/2)
  280. for _, o := range output {
  281. d.Write(centering + o + door.Reset + door.CRNL)
  282. }
  283. d.Write(door.CRNL)
  284. }
  285. press_a_key(d)
  286. var descent door.ColorFont = FontDescent()
  287. output, l = descent.Output("Meanwhile...")
  288. if l > door.Width {
  289. output, l = descent.Output("BUGZ")
  290. }
  291. if l < door.Width {
  292. centering = strings.Repeat(" ", (door.Width-l)/2)
  293. for _, o := range output {
  294. d.Write(centering + o + door.Reset + door.CRNL)
  295. }
  296. d.Write(door.CRNL)
  297. }
  298. var remorse door.ColorFont = FontRemorse()
  299. output, l = remorse.Output("Enjoy the fonts")
  300. if l > door.Width {
  301. output, l = remorse.Output("Amazing")
  302. }
  303. if l < door.Width {
  304. centering = strings.Repeat(" ", (door.Width-l)/2)
  305. for _, o := range output {
  306. d.Write(centering + o + door.Reset + door.CRNL)
  307. }
  308. d.Write(door.CRNL)
  309. }
  310. var dungeon door.ColorFont = FontDungeon()
  311. output, l = dungeon.Output("Until NEXT time")
  312. if l > door.Width {
  313. output, l = dungeon.Output("Beware")
  314. }
  315. if l < door.Width {
  316. centering = strings.Repeat(" ", (door.Width-l)/2)
  317. for _, o := range output {
  318. d.Write(centering + o + door.Reset + door.CRNL)
  319. }
  320. d.Write(door.CRNL)
  321. }
  322. /*
  323. redgreen := FontArmageddon()
  324. white := redgreen.Scan(7)
  325. blue := redgreen.Scan(4)
  326. redgreen.Modify(1, white)
  327. redgreen.Modify(2, blue)
  328. */
  329. redgreen := FontRedGreen()
  330. output, l = redgreen.Output("Red-Green")
  331. if l < door.Width {
  332. press_a_key(d)
  333. centering = strings.Repeat(" ", (door.Width-l)/2)
  334. for _, o := range output {
  335. d.Write(centering + o + door.Reset + door.CRNL)
  336. }
  337. d.Write(door.CRNL)
  338. output, l = redgreen.Output("Software")
  339. centering = strings.Repeat(" ", (door.Width-l)/2)
  340. for _, o := range output {
  341. d.Write(centering + o + door.Reset + door.CRNL)
  342. }
  343. d.Write(door.CRNL)
  344. }
  345. }
  346. func input_demo(d *door.Door) {
  347. var ticker *time.Ticker = time.NewTicker(time.Second)
  348. go func() {
  349. for t := range ticker.C {
  350. const tf = "January 2, 2006 03:04:05 PM MST"
  351. output := door.SavePos + door.Goto(5, 2) + door.ColorText("BRI WHI ON CYAN") + t.Format(tf) + door.RestorePos
  352. d.Write(output)
  353. }
  354. }()
  355. var inputColor string = door.ColorText("BRI WHI ON BLUE")
  356. var inputColor2 string = door.ColorText("BRI WHI ON GREEN")
  357. var prompt door.Line = door.Line{Text: "What is YOUR Name: "}
  358. prompt.RenderF = door.RenderBlueYellow
  359. d.Write(prompt.Output() + inputColor)
  360. var name string = d.Input(25)
  361. d.Write(door.Reset + door.CRNL)
  362. prompt.Text = "What is Your Quest: "
  363. d.Write(prompt.Output() + inputColor2)
  364. var quest string = d.Input(35)
  365. d.Write(door.Reset + door.CRNL)
  366. prompt.Text = "What is your Favorite CoLoR: "
  367. d.Write(prompt.Output() + inputColor)
  368. var color string = d.Input(15)
  369. d.Write(door.Reset + door.CRNL)
  370. ticker.Stop()
  371. d.Write(fmt.Sprintf("You're %s on the %s quest, and fond of %s."+door.CRNL, name, quest, color))
  372. }
  373. func progress_bars(d *door.Door) {
  374. d.Write(door.Clrscr)
  375. var bar door.BarLine = door.BarLine{Line: door.Line{DefaultColor: door.ColorText("BOLD YELLOW")}, Width: 20, Style: door.HALF_STEP}
  376. var bar2 door.BarLine = door.BarLine{Width: 30, Style: door.SOLID, PercentStyle: door.PERCENT_SPACE}
  377. bar2.ColorRange = []door.BarRange{
  378. {2500, door.ColorText("RED")},
  379. {5000, door.ColorText("BROWN")},
  380. {7500, door.ColorText("BOLD YEL")},
  381. {9500, door.ColorText("GREEN")},
  382. {10100, door.ColorText("BRI GRE")}}
  383. var bar3 door.BarLine = door.BarLine{Width: 15, Style: door.GRADIENT, Line: door.Line{DefaultColor: door.ColorText("CYAN")}}
  384. var percentage int64
  385. bar.UpdateP = pctUpdate(&percentage)
  386. bar2.UpdateP = pctUpdate(&percentage)
  387. bar3.UpdateP = pctUpdate(&percentage)
  388. update_bars := func() {
  389. bar.Update()
  390. bar2.Update()
  391. bar3.Update()
  392. }
  393. d.Write(door.Goto(3, 12) + "Half-Step")
  394. d.Write(door.Goto(25, 12) + "% with space and Color Range")
  395. d.Write(door.Goto(57, 12) + "Gradient")
  396. d.Write(door.HideCursor)
  397. bar_start := door.Goto(3, 15)
  398. for f := 0; f <= 100; f++ {
  399. d.Write(door.Goto(3, 10) + door.Reset + fmt.Sprintf("Value: %d", f))
  400. percentage = int64(f * 100)
  401. update_bars()
  402. d.Write(bar_start + bar.Output() + " " + door.Reset + bar2.Output() + door.Reset + " " + bar3.Output())
  403. if d.Disconnect() {
  404. // don't continue to sleep if we're disconnected
  405. break
  406. }
  407. time.Sleep(time.Millisecond * 100)
  408. }
  409. d.Write(door.ShowCursor)
  410. }
  411. func width_demo(d *door.Door) {
  412. var w int = door.Width
  413. var panel door.Panel = door.Panel{X: 1, Y: 1, Width: w}
  414. var lineColor string = door.ColorText("WHI")
  415. var line string
  416. for y := 1; y <= door.Height; y++ {
  417. if y%10 == 0 {
  418. line = strings.Repeat("1234567890", w/10)
  419. for x := len(line); x < w; x++ {
  420. line += strconv.Itoa((x + 1) % 10)
  421. }
  422. } else {
  423. line = ""
  424. for x := 1; x < w; x++ {
  425. if x%10 == 0 {
  426. line += strconv.Itoa(y % 10)
  427. } else {
  428. line += " "
  429. }
  430. }
  431. }
  432. var l door.Line = door.Line{Text: line, DefaultColor: lineColor}
  433. panel.Lines = append(panel.Lines, l)
  434. }
  435. var message string = fmt.Sprintf("Screen Size: %d X %d", door.Width, door.Height)
  436. d.Write(panel.Output())
  437. // Output alert on top of panel
  438. var cx, cy int
  439. cx = (door.Width - len(message) + 2) / 2
  440. cy = (door.Height - 3) / 2
  441. var alert []string = door.AlertBox(message, 1)
  442. d.Write(door.ColorText("BRI YEL ON BLUE"))
  443. for idx, ab := range alert {
  444. d.Write(door.Goto(cx, cy+idx) + ab)
  445. }
  446. d.Write(door.Reset + panel.GotoEnd())
  447. // Pause for key
  448. d.Key()
  449. panel.Lines = make([]door.Line, 0)
  450. var background string = "BUGZ Test Door in GO "
  451. var bl int = len(background)
  452. for y := 1; y <= door.Height; y++ {
  453. offset := (y - 1) % bl
  454. line = background[offset:]
  455. for len(line) < w {
  456. if len(line)+bl <= w {
  457. line += background
  458. } else {
  459. line += background[0 : w-len(line)]
  460. }
  461. }
  462. var l door.Line = door.Line{Text: line, RenderF: door.RenderBlueYellow}
  463. panel.Lines = append(panel.Lines, l)
  464. }
  465. d.Write(panel.Output())
  466. d.Key()
  467. }
  468. func panel_demo(d *door.Door) {
  469. var width int = 55
  470. var panel door.Panel = door.Panel{X: 5, Y: 5, Width: width, Style: door.DOUBLE, BorderColor: door.ColorText("CYAN ON BLUE"), Title: "[ Panel Demo ]"}
  471. var lineColor string = door.ColorText("BRIGHT WHI ON BLUE")
  472. // Add lines to the panel
  473. for _, line := range []string{"The BBS Door Panel Demo", "(C) 2021 Red Green Software, https://red-green.com"} {
  474. if door.Unicode {
  475. line = strings.Replace(line, "(C)", "\u00a9", -1)
  476. }
  477. var l door.Line = door.Line{Text: line, Width: width, DefaultColor: lineColor}
  478. panel.Lines = append(panel.Lines, l)
  479. }
  480. panel.Lines = append(panel.Lines, panel.Spacer())
  481. panel.Lines = append(panel.Lines, door.Line{Text: "Welcome to golang!", Width: width, DefaultColor: lineColor})
  482. width = 10
  483. var single door.Panel = door.Panel{X: 6, Y: 12, Width: width, Style: door.SINGLE, BorderColor: door.ColorText("WHITE ON BLUE"), Title: "< Single >"}
  484. single.Lines = append(single.Lines, door.Line{Text: "Example", Width: width, DefaultColor: door.ColorText("WHI ON BLACK")})
  485. single.Lines = append(single.Lines, single.Spacer())
  486. single.Lines = append(single.Lines, door.Line{Text: "More Text", Width: width, DefaultColor: door.ColorText("BRI GREEN ON BLACK")})
  487. width = 15
  488. var double_single door.Panel = door.Panel{X: 26, Y: 12, Width: width, Style: door.DOUBLE_SINGLE, BorderColor: door.ColorText("BRI CYAN ON GREEN"), Title: "Double", TitleOffset: 3}
  489. double_single.Lines = append(double_single.Lines, door.Line{Text: "Double / Single", Width: width, DefaultColor: door.ColorText("BRI WHI ON GREEN")})
  490. double_single.Lines = append(double_single.Lines, double_single.Spacer())
  491. double_single.Lines = append(double_single.Lines, door.Line{Text: "Some Other Text", Width: width, DefaultColor: door.ColorText("BRI CYAN ON GREEN")})
  492. var single_double door.Panel = door.Panel{X: 46, Y: 12, Width: width, Style: door.SINGLE_DOUBLE, BorderColor: door.ColorText("BRI YELL ON RED")}
  493. single_double.Lines = append(single_double.Lines, door.Line{Text: "Single / Double", Width: width, DefaultColor: door.ColorText("BRI WHI ON RED")})
  494. single_double.Lines = append(single_double.Lines, single_double.Spacer())
  495. single_double.Lines = append(single_double.Lines, door.Line{Text: "Text Goes Here ", Width: width, DefaultColor: door.ColorText("BRI GREEN ON RED")})
  496. d.Write(door.Clrscr)
  497. d.Write(panel.Output())
  498. d.Write(single.Output())
  499. d.Write(double_single.Output())
  500. d.Write(single_double.Output())
  501. }
  502. type SpinRite struct {
  503. Width uint8 // Width of the animation (must be odd)
  504. Length uint8 // Width of the worm (must be odd)
  505. Color string // Color (default CYAN ON BLUE)
  506. OutputB []byte // Output CP437/bytes (Width)
  507. OutputR []rune // Output Unicode (Width)
  508. Buffer []uint8 // Output calculate buffer (Width)
  509. Runes []rune // blank, center, top, bottom, both
  510. Bytes []byte // blank, center, top, bottom, both
  511. CenterPos uint8 // Center Position (Width - 1) / 2
  512. StartPos uint8 // Starting Position (Length -1) / 2
  513. Index uint8 // Index of current iteration
  514. }
  515. func SpinRiteInit(width uint8, length uint8, color string) SpinRite {
  516. if color == "" {
  517. color = door.ColorText("CYAN ON BLUE")
  518. }
  519. var center uint8 = ((width - 1) / 2)
  520. var start uint8 = ((length - 1) / 2)
  521. var result SpinRite = SpinRite{Width: width,
  522. Length: length,
  523. Color: color,
  524. CenterPos: center,
  525. StartPos: start,
  526. Buffer: make([]uint8, width),
  527. Index: 0}
  528. if door.Unicode {
  529. result.OutputR = make([]rune, width)
  530. result.Runes = []rune{' ', '\u221e', '\u2580', '\u2584', '\u2588'}
  531. } else {
  532. result.OutputB = make([]byte, width)
  533. result.Bytes = []byte{' ', 0xec, 0xdf, 0xdc, 0xdb}
  534. }
  535. return result
  536. }
  537. func (sr *SpinRite) PosToIndex(pos int8, top bool) (index uint8, level bool) {
  538. if top {
  539. if pos >= int8(sr.Width) {
  540. // wrap around
  541. level = !top
  542. idx := int8(sr.Width) + (int8(sr.Width) - (pos + 1))
  543. log.Println("idx", idx) // -13
  544. index = uint8(idx)
  545. } else {
  546. level = top
  547. index = uint8(pos)
  548. }
  549. } else {
  550. // bottom
  551. if pos < 0 {
  552. level = !top
  553. pos++
  554. index = uint8(-pos)
  555. } else {
  556. level = top
  557. index = uint8(pos)
  558. }
  559. }
  560. return
  561. }
  562. func (sr *SpinRite) Calculate() {
  563. for i := range sr.Buffer {
  564. sr.Buffer[i] = 0
  565. }
  566. sr.Buffer[sr.CenterPos] = 1
  567. // [ S C s ]
  568. var top int8 = int8(sr.CenterPos) - int8(sr.StartPos) + int8(sr.Index)
  569. var bottom int8 = int8(sr.CenterPos) + int8(sr.StartPos) - int8(sr.Index)
  570. var l int8
  571. for l = 0; l < int8(sr.Length); l++ {
  572. var index uint8
  573. var level bool
  574. index, level = sr.PosToIndex(top+l, true)
  575. log.Println("TOP", l, top+l, index, level)
  576. if level {
  577. sr.Buffer[index] |= 0x02
  578. } else {
  579. sr.Buffer[index] |= 0x04
  580. }
  581. index, level = sr.PosToIndex(bottom-l, false)
  582. log.Println("BOT", l, bottom-l, index, level)
  583. if level {
  584. sr.Buffer[index] |= 0x02
  585. } else {
  586. sr.Buffer[index] |= 0x04
  587. }
  588. }
  589. log.Println("Index", sr.Index, "Buffer", sr.Buffer)
  590. var reset bool = true
  591. // Convert from buffer to output
  592. if door.Unicode {
  593. for l = 0; l < int8(sr.Width); l++ {
  594. switch sr.Buffer[l] {
  595. case 0:
  596. sr.OutputR[l] = sr.Runes[0]
  597. case 1:
  598. sr.OutputR[l] = sr.Runes[1]
  599. reset = false
  600. case 2, 3:
  601. sr.OutputR[l] = sr.Runes[2]
  602. reset = false
  603. case 4, 5:
  604. sr.OutputR[l] = sr.Runes[3]
  605. reset = false
  606. case 6, 7:
  607. sr.OutputR[l] = sr.Runes[4]
  608. }
  609. }
  610. } else {
  611. for l = 0; l < int8(sr.Width); l++ {
  612. switch sr.Buffer[l] {
  613. case 0:
  614. sr.OutputB[l] = sr.Bytes[0]
  615. case 1:
  616. sr.OutputB[l] = sr.Bytes[1]
  617. reset = false
  618. case 2, 3:
  619. sr.OutputB[l] = sr.Bytes[2]
  620. reset = false
  621. case 4, 5:
  622. sr.OutputB[l] = sr.Bytes[3]
  623. reset = false
  624. case 6, 7:
  625. sr.OutputB[l] = sr.Bytes[4]
  626. }
  627. }
  628. }
  629. if reset {
  630. log.Println("RESET")
  631. sr.Index = 0
  632. }
  633. }
  634. func (sr *SpinRite) Output() string {
  635. var result string
  636. sr.Calculate()
  637. if door.Unicode {
  638. result = string(sr.OutputR)
  639. } else {
  640. result = string(sr.OutputB)
  641. }
  642. sr.Index++
  643. return sr.Color + result
  644. }
  645. /*
  646. Or possibly: · ∞
  647. [ █████ ]
  648. [ ▄▄███▀▀ ]
  649. [ ▄▄▄▄█▀▀▀▀ ]
  650. [ ▄▄▄▄▄•▀▀▀▀▀ ]
  651. [▄▄▄▄▄ • ▀▀▀▀▀]
  652. [█▄▄▄ • ▀▀▀█]
  653. [██▄ • ▀██]
  654. [██▀ • ▄██]
  655. [█▀▀▀ • ▄▄▄█]
  656. [█▀▀▀▀ • ▄▄▄▄█]
  657. [ ▀▀▀▀▀•▄▄▄▄▄ ]
  658. [ ▀▀▀▀█▄▄▄▄ ]
  659. [ ▀▀███▄▄ ]
  660. */
  661. func main() {
  662. var message string
  663. fmt.Println("Starting testdoor.go")
  664. var d door.Door = door.Door{}
  665. d.Init("testdoor")
  666. defer func() {
  667. if err := recover(); err != nil {
  668. // This displays stack trace stderr
  669. debug.PrintStack()
  670. fmt.Println("ERROR:", err)
  671. log.Println("FAILURE:", err)
  672. // Display error to user
  673. d.Write(fmt.Sprintf(door.Reset+door.CRNL+"Exception: %v"+door.CRNL, err))
  674. }
  675. }()
  676. defer d.Close()
  677. // var ticker *time.Ticker = time.NewTicker(time.Second)
  678. var ticker *time.Ticker = time.NewTicker(time.Millisecond * time.Duration(100))
  679. var spin SpinRite = SpinRiteInit(13, 5, door.ColorText("RED ON GREEN"))
  680. var spin2 SpinRite = SpinRiteInit(15, 5, door.ColorText("BRI CYA ON BLUE"))
  681. go func() {
  682. var output string
  683. for _ = range ticker.C {
  684. output = door.SavePos + door.Goto(door.Width-15, 1) + spin.Output() +
  685. door.Goto(door.Width-16, 2) + spin2.Output() + door.RestorePos
  686. if !d.Disconnect() {
  687. d.Write(output)
  688. } else {
  689. ticker.Stop()
  690. return
  691. }
  692. }
  693. }()
  694. if false {
  695. go func() {
  696. var maxlen int = 0 // max length of timeinfo (sysops have 4 digits of mins)
  697. for t := range ticker.C {
  698. const tf = "03:04:05 PM"
  699. var timeinfo string = " " + t.Format(tf) + " " + fmt.Sprintf("(%3.1f mins)", d.TimeLeft().Minutes()) + " "
  700. if maxlen == 0 {
  701. maxlen = len(timeinfo)
  702. } else {
  703. if len(timeinfo) < maxlen {
  704. timeinfo += strings.Repeat(" ", maxlen-len(timeinfo))
  705. }
  706. }
  707. // maxlen = 12 + 7 + 5 = 24
  708. output := door.SavePos + door.Goto(door.Width-(maxlen+1), 0) + door.ColorText("BRI WHI ON BLUE") + timeinfo + door.RestorePos
  709. if !d.Disconnect() {
  710. d.Write(output)
  711. } else {
  712. ticker.Stop()
  713. return
  714. }
  715. }
  716. }()
  717. }
  718. // bold := door.Color(1, 37, 40)
  719. var bolder string = door.ColorText("BLI BOLD YEL ON BLUE")
  720. d.Write("Welcome to " + bolder + "door32.sys" + door.Reset + door.CRNL + "..." + door.CRNL)
  721. // d.Write("\x1b[?9h") // enable mouse X10 support
  722. d.Write("\x1b[?1000h") // enable mouse
  723. press_keys(&d)
  724. // press_a_key(&d)
  725. d.Write(door.CRNL)
  726. var b []string = door.AlertBox("Warning: golang is in use!", 1)
  727. d.Write(door.ColorText("BRI WHI ON GREEN"))
  728. for _, line := range b {
  729. d.Write(line + door.CRNL)
  730. }
  731. d.Write(door.Reset + door.CRNL)
  732. var left time.Duration = d.TimeLeft()
  733. message = fmt.Sprintf("You have %0.2f minutes / %0.2f seconds remaining..."+door.CRNL, left.Minutes(), left.Seconds())
  734. d.Write(message)
  735. press_keys(&d)
  736. // press_a_key(&d)
  737. var mainmenu door.Menu = MainMenu()
  738. var choice int
  739. for choice >= 0 {
  740. d.Write(door.Clrscr + door.HideCursor)
  741. choice = mainmenu.Choose(&d)
  742. d.Write(door.ShowCursor)
  743. if choice < 0 {
  744. break
  745. }
  746. option := mainmenu.GetOption(choice)
  747. // fmt.Printf("Choice: %d, Option: %c\n", choice, option)
  748. switch option {
  749. case 'A':
  750. display_ansi(&d)
  751. press_a_key(&d)
  752. case 'D':
  753. display_information(&d)
  754. press_a_key(&d)
  755. case 'F':
  756. font_demo(&d)
  757. press_a_key(&d)
  758. case 'I':
  759. d.Write(door.Reset + door.CRNL + door.CRNL)
  760. input_demo(&d)
  761. press_a_key(&d)
  762. case 'M':
  763. d.Write(door.Reset + door.CRNL + "TO DO: Provide menu of options to select from..." + door.CRNL)
  764. press_a_key(&d)
  765. case 'P':
  766. progress_bars(&d)
  767. press_a_key(&d)
  768. case 'S':
  769. panel_demo(&d)
  770. press_a_key(&d)
  771. case 'T':
  772. about_test_door(&d)
  773. press_a_key(&d)
  774. case 'W':
  775. width_demo(&d)
  776. case 'Q':
  777. choice = -1
  778. case 'C': // Disabled
  779. var a, z int
  780. z = 0
  781. a = 10 / z
  782. z = a
  783. _ = a
  784. _ = z
  785. }
  786. }
  787. d.Write(door.Reset + door.CRNL)
  788. message = fmt.Sprintf("Returning to the %s BBS..."+door.CRNL, d.Config.BBSID)
  789. d.Write(message)
  790. d.WaitKey(1, 0)
  791. left = d.TimeLeft()
  792. ticker.Stop()
  793. message = fmt.Sprintf("You had %0.2f minutes remaining!"+door.CRNL, left.Minutes())
  794. d.Write(message)
  795. left = d.TimeUsed()
  796. d.Write(fmt.Sprintf("You used %0.2f seconds / %0.2f minutes."+door.CRNL, left.Seconds(), left.Minutes()))
  797. fmt.Println("Ending testdoor.go")
  798. }