Author Topic: A quick selection menu  (Read 6746 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
A quick selection menu
« on: August 10, 2019, 12:08:19 am »
For the first time in I don't know when, I finally coded a piece of a program which makes use of that elusive bit command XOR!

Code: QB64: [Select]
  1.  
  2. DEFLNG A-Z
  3. CONST Skyblue~& = &HFF87CEEB
  4. CONST Gold~& = &HFFFFD700
  5. CONST Black~& = &HFF000000
  6. CONST LightGray~& = &HFFD3D3D3
  7.  
  8.  
  9. SCREEN _NEWIMAGE(640, 480, 32)
  10.  
  11. DIM SHARED F150, F50, F25, F15
  12. F150 = _LOADFONT("courbd.ttf", 150)
  13. F50 = _LOADFONT("courbd.ttf", 50)
  14. F25 = _LOADFONT("courbd.ttf", 25)
  15. F15 = _LOADFONT("courbd.ttf", 20)
  16.  
  17. TYPE OptionType
  18.     x AS INTEGER
  19.     y AS INTEGER
  20.     wide AS INTEGER
  21.     high AS INTEGER
  22.     choices AS INTEGER 'from 0 to choices, so subtract 1 from total number of choices
  23.     captions AS STRING ' "12345678901234567890" --10 spaces per choice, so the left would represent two choices
  24.     clicks AS INTEGER 'binary value of click state for our choices; up to 16 max
  25.     Font AS INTEGER
  26.  
  27. DIM SHARED Options(1 TO 3) AS OptionType
  28.  
  29. Options(1).x = 70: Options(1).y = 100: Options(1).high = 50: Options(1).wide = 100 '1 is mode
  30. Options(1).choices = 4: Options(1).captions = "+         -        *          /         RND       "
  31. Options(1).Font = F25: Options(1).clicks = 16 'rnd selected as default
  32.  
  33. Options(2).x = 70: Options(2).y = 200: Options(2).high = 50: Options(2).wide = 100 '2 is time
  34. Options(2).choices = 4: Options(2).captions = "15        30       60         120       300       "
  35. Options(2).Font = F25: Options(2).clicks = 4 '60 second default game
  36.  
  37. Options(3).x = 70: Options(3).y = 300: Options(3).high = 50: Options(3).wide = 100 '3 is difficulty
  38. Options(3).choices = 4:: Options(3).captions = "TRIVIAL   EASY     AVERAGE    HARD      INSANE    "
  39. Options(3).Font = F15: Options(3).clicks = 4 'average default setting
  40.  
  41.  
  42.  
  43.  
  44.     SetupOptions
  45.  
  46.  
  47.     _LIMIT 60
  48.  
  49.  
  50.  
  51. SUB SetupOptions
  52.     s = SaveState
  53.     DO
  54.         _LIMIT 30
  55.         CLS
  56.         FOR i = 1 TO 3 '3 option sets to display
  57.             _FONT Options(i).Font
  58.             x1 = Options(i).x: y1 = Options(i).y
  59.             w = Options(i).wide: h = Options(i).high
  60.             clicks = Options(i).clicks
  61.             FOR j = 0 TO Options(i).choices
  62.                 t$ = _TRIM$(MID$(Options(i).captions, j * 10, 10))
  63.                 IF clicks AND 2 ^ j THEN
  64.                     COLOR Black, 0: BoxTitle x1 + j * w, y1, w, h, 3, Skyblue, Gold, t$
  65.                 ELSE
  66.                     COLOR LightGray, 0: BoxTitle x1 + j * w, y1, w, h, 3, Black, Gold, t$
  67.                 END IF
  68.             NEXT
  69.         NEXT
  70.         _DISPLAY
  71.         WHILE _MOUSEINPUT: WEND
  72.  
  73.         IF _MOUSEBUTTON(1) AND NOT oldmouse THEN 'if button was up, but is now down, then it's a click
  74.             ClickX = INT((_MOUSEX - 70) / 100): ClickY = _CEIL((_MOUSEY - 100) / 50)
  75.             IF ClickX >= 0 AND ClickX <= 4 THEN 'Click on menu item 0 to 4
  76.                 SELECT CASE ClickY '1 = top , 3 = middle, 5 = bottom
  77.                     CASE 1
  78.                         IF 2 ^ ClickX = 16 THEN
  79.                             IF Options(1).clicks AND 16 THEN Options(1).clicks = 0 ELSE Options(1).clicks = 16
  80.                         ELSE
  81.                             Options(1).clicks = Options(1).clicks XOR 2 ^ ClickX
  82.                             IF Options(1).clicks <> 16 THEN Options(1).clicks = Options(1).clicks AND NOT 16
  83.                         END IF
  84.                     CASE 3, 5
  85.                         Options(ClickY \ 2 + 1).clicks = 2 ^ ClickX
  86.                 END SELECT
  87.             END IF
  88.         END IF
  89.         oldmouse = _MOUSEBUTTON(1)
  90.     LOOP
  91.     RestoreState s
  92.  
  93.  
  94. SUB BoxTitle (x1, y1, x2, y2, thick, fg AS _UNSIGNED LONG, bg AS _UNSIGNED LONG, title$)
  95.     Box x1, y1, x2, y2, thick, fg, bg
  96.     CenterText x1, y1 + thick, x1 + x2, y1 + y2 + thick, title$
  97.  
  98.  
  99. SUB Box (x, y, wide, high, thick, Kolor AS _UNSIGNED LONG, Trim AS _UNSIGNED LONG)
  100.     LINE (x, y)-STEP(wide, high), Kolor, BF
  101.     FOR i = 0 TO thick - 1
  102.         LINE (x + i, y + i)-STEP(wide - 2 * i, high - 2 * i), Trim, B
  103.     NEXT
  104.  
  105.  
  106. SUB CenterText (x1, y1, x2, y2, text$)
  107.     text$ = _TRIM$(text$)
  108.     xmax = x2 - x1: ymax = y2 - y1
  109.     textlength = _PRINTWIDTH(text$)
  110.     xpos = (xmax - textlength) / 2
  111.     ypos = (ymax - _FONTHEIGHT) / 2
  112.     _PRINTSTRING (x1 + xpos, y1 + ypos), text$
  113.  
  114. FUNCTION SaveState
  115.     TYPE SaveStateType
  116.         InUse AS INTEGER
  117.         DC AS INTEGER
  118.         BG AS INTEGER
  119.         F AS INTEGER
  120.         D AS INTEGER
  121.         S AS INTEGER
  122.         Disp AS INTEGER
  123.         CurX AS INTEGER
  124.         CurY AS INTEGER
  125.     END TYPE
  126.     DIM SS AS SaveStateType, Temp AS SaveStateType
  127.     SHARED NSS AS LONG 'Number of Saved States
  128.     SHARED SaveMem AS _MEM
  129.     IF NOT _MEMEXISTS(SaveMem) THEN
  130.         SaveMem = _MEMNEW(LEN(SS) * 255) 'Save up to 255 save states; More than 255 and we toss an error
  131.         $CHECKING:OFF
  132.         _MEMFILL SaveMem, SaveMem.OFFSET, SaveMem.SIZE, 0 AS _UNSIGNED _BYTE
  133.         $CHECKING:ON
  134.     END IF
  135.  
  136.     'Data to Save
  137.     SS.InUse = -1
  138.     SS.F = _FONT
  139.     SS.DC = _DEFAULTCOLOR
  140.     SS.BG = _BACKGROUNDCOLOR
  141.     SS.D = _DEST
  142.     SS.S = _SOURCE
  143.     SS.Disp = _AUTODISPLAY
  144.     SS.CurX = POS(0)
  145.     SS.CurY = CSRLIN
  146.     FOR i = 1 TO NSS
  147.         O = (i - 1) * LEN(SS)
  148.         _MEMGET SaveMem, SaveMem.OFFSET + O, Temp
  149.         IF Temp.InUse = 0 THEN
  150.             _MEMPUT SaveMem, SaveMem.OFFSET + O, SS
  151.             SaveState = i
  152.             EXIT FUNCTION
  153.         END IF
  154.     NEXT
  155.     _MEMPUT SaveMem, SaveMem.OFFSET + NSS * LEN(SS), SS
  156.     NSS = NSS + 1
  157.     SaveState = NSS
  158.  
  159. SUB RestoreState (WhichOne AS LONG)
  160.     DIM SS AS SaveStateType
  161.     SHARED NSS AS LONG 'Number of Saved States
  162.     SHARED SaveMem AS _MEM
  163.     _MEMGET SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
  164.     IF SS.InUse THEN
  165.         SS.InUse = 0 'Let the routine know that we're no longer in use for this handle
  166.         $CHECKING:OFF
  167.         _MEMPUT SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
  168.         $CHECKING:ON
  169.         _FONT SS.F
  170.         COLOR SS.DC, SS.BG
  171.         _DEST SS.D
  172.         _SOURCE SS.S
  173.         IF SS.Disp THEN _AUTODISPLAY ELSE _DISPLAY
  174.         LOCATE SS.CurY, SS.CurX
  175.     END IF
  176.  

Options(1).clicks = Options(1).clicks XOR 2 ^ ClickX   <-- This is the line which toggles the first four selections of the top line on and off for us, allowing us to choose if we want to use one or more of them. 

XOR is such a rare command for me to actually use in one of my own programs, I just had to share so somebody could see an actual physical demonstration of its use, without it being in something overly complex like a hash table formula or whatnot.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Richard Frost

  • Seasoned Forum Regular
  • Posts: 316
  • Needle nardle noo. - Peter Sellers
    • View Profile
Re: A quick selection menu
« Reply #1 on: August 10, 2019, 10:24:26 am »
I use XOR a lot to toggle between 0 and 1.

var = var XOR 1

Doesn't it look nicer than "var = 1 - var"?

Even longer and sillier is "if var = 0 then var = 1 else var = 0".

It works better if you plug it in.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: A quick selection menu
« Reply #2 on: August 10, 2019, 10:45:49 am »
I use XOR a lot to toggle between 0 and 1.

var = var XOR 1

Doesn't it look nicer than "var = 1 - var"?

Even longer and sillier is "if var = 0 then var = 1 else var = 0".

That does look better!
I've used:
toggle = (toggle + 1) mod 2

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: A quick selection menu
« Reply #3 on: August 10, 2019, 10:56:22 am »
That does look better!
I've used:
toggle = (toggle + 1) mod 2

toggle = -(toggle -1)  :P
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: A quick selection menu
« Reply #4 on: August 10, 2019, 01:18:03 pm »
what do you think of
Quote
toggle = ABS(toggle -1)
?
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: A quick selection menu
« Reply #5 on: August 10, 2019, 01:52:48 pm »
I think it works! :D
Code: QB64: [Select]
  1.     toggle = ABS(toggle - 1)
  2.     'toggle = toggle XOR 1
  3.     PRINT toggle
  4.     INPUT "OK enter.."; w$
  5.  

But XOR still gets my vote for elegance.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: A quick selection menu
« Reply #6 on: August 10, 2019, 02:07:45 pm »
Speaking of menu's and bit math (or was it binary), I remember a thing about assigning pizza orders a number.

It goes something like this:

A pepperoni (only) pizza is a number 1
A sausage (only) pizza is a number 2
A pepperoni and sauge pizza is a number 3
A onion (only) pizza is a number 4
A pepperoni and onion pizza is a number 5
A sausage and onion pizza is a number 6
A pepperoni, sausage and onion pizza is a number 7
A mushroom (only) is a number 8
A pepperoni and mushroom is a number 9
...

If you are wondering where I am going with this, I am going to grab a byte to eat :D
 

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: A quick selection menu
« Reply #7 on: August 10, 2019, 05:06:54 pm »
Yeah, pizza!
At home this evening my family has had pizza margherita  https://cucina.fanpage.it/pizza-margherita-fatta-in-casa/and pizza diavola https://www.gustissimo.it/ricette/pizze/pizza-alla-diavola.htm.
Two classical options of pizza here in the neighbour of Naples.

Beware of taste of pizza or you can become this https://cdn-italiani-media.italiani.it/site-italiani/2017/12/pizza-napoletana-patrimonio-dellUNESCO-3-1024x761.png
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: A quick selection menu
« Reply #8 on: August 10, 2019, 05:51:09 pm »
wait...

toggle = 1 - toggle 'works ? yes!

dang! New #1 in elegance!

pepperoni    yes/no
sausage      yes/no
onion          yes/no
mushroom   yes/no
pepper        yes/no
xtra cheese yes/no
xtra sauce   yes/no
anchovies   yes/no/hell no!

we have enough choices to make a byte.

Offline pforpond

  • Newbie
  • Posts: 76
  • I am me
    • View Profile
Re: A quick selection menu
« Reply #9 on: August 11, 2019, 06:01:23 am »
I don't know why but I get a compilation error with this. Is there something I'm missing? I'm happy to check out the compilelog.txt if needed :)
Screenshot 2019-08-11 at 10.59.49.png
* Screenshot 2019-08-11 at 10.59.49.png (Filesize: 275.64 KB, Dimensions: 1504x1068, Views: 277)
Loading Signature...

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: A quick selection menu
« Reply #10 on: August 11, 2019, 10:47:15 am »
Hi Steve,

I am trying a mod of this menu system for pizza ordering app and using OPTION _EXPLICIT checking.

I ran into this which I am uncertain how to handle, see attached

Just DIM in SUB is not working.
should this be declared in main or static.PNG
* should this be declared in main or static.PNG (Filesize: 19.55 KB, Dimensions: 901x433, Views: 231)

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: A quick selection menu
« Reply #11 on: August 12, 2019, 12:59:33 am »
Well after a few modifications, I got the pizza thing going:

Code: QB64: [Select]
  1. _TITLE "Get Your Pizza Here" 'by Steve McNeill mods by B+ copied and mod 2019-08-11
  2. ' 2019-08-10 bplus wants to try out a pizza ordering menu for a resturant app
  3. ' Testing my Mesage Box with Steve's SaveState and RestoreState procedures works!
  4.  
  5. ' ???????????????????????????   every now and again a miniture but fully fuctional screen comes up ???????????
  6.  
  7. DEFLNG A-Z
  8. CONST Skyblue~& = &HFF87CEEB
  9. CONST Gold~& = &HFFFFD700
  10. CONST Black~& = &HFF000000
  11. CONST LightGray~& = &HFFD3D3D3
  12.  
  13. SCREEN _NEWIMAGE(1240, 350, 32)
  14. _SCREENMOVE 100, 20
  15.  
  16. DIM SHARED F150, F50, F25, F15
  17. F150 = _LOADFONT("courbd.ttf", 150)
  18. F50 = _LOADFONT("courbd.ttf", 50)
  19. F25 = _LOADFONT("courbd.ttf", 25)
  20. F15 = _LOADFONT("courbd.ttf", 20)
  21.  
  22. TYPE SaveStateType
  23.     InUse AS INTEGER
  24.     DC AS INTEGER
  25.     BG AS INTEGER
  26.     F AS INTEGER
  27.     D AS INTEGER
  28.     S AS INTEGER
  29.     Disp AS INTEGER
  30.     CurX AS INTEGER
  31.     CurY AS INTEGER
  32. DIM SHARED NSS AS LONG 'Number of Saved States
  33. DIM SHARED SaveMem AS _MEM
  34.  
  35. TYPE OptionType
  36.     x AS INTEGER
  37.     y AS INTEGER
  38.     wide AS INTEGER
  39.     high AS INTEGER
  40.     choices AS INTEGER 'from 0 to choices, so subtract 1 from total number of choices
  41.     captions AS STRING ' "12345678901234567890" --10 spaces per choice, so the left would represent two choices
  42.     clicks AS STRING '0 and 1 string
  43.     Font AS INTEGER
  44.  
  45. DIM SHARED nOptions
  46. nOptions = 3
  47. DIM SHARED Options(1 TO nOptions) AS OptionType
  48.  
  49. DIM mArray(7) AS STRING * 10, i, j, menu$, mx, my, kh, o, total!, ttl$
  50. mArray(0) = "Pepperoni"
  51. mArray(1) = "Sausage"
  52. mArray(2) = "Onion"
  53. mArray(3) = "Mushroom"
  54. mArray(4) = "Peppers"
  55. mArray(5) = "X Cheese"
  56. mArray(6) = "X Sauce"
  57. mArray(7) = "Anchovies"
  58. FOR i = 0 TO 7 'build captions string
  59.     menu$ = menu$ + mArray(i)
  60.  
  61. ' 10 chars captions fixed length string*10  Really only nine characters fit
  62. Options(1).x = 20: Options(1).y = 50: Options(1).high = 50: Options(1).wide = 150 '1 is mode
  63. Options(1).choices = 7: Options(1).captions = menu$
  64. Options(1).Font = F15: Options(1).clicks = STRING$(Options(1).choices + 1, "0") 'rnd selected as default 'b+??????????????
  65.  
  66. Options(2).x = 470: Options(2).y = 150: Options(2).high = 50: Options(2).wide = 150
  67. Options(2).choices = 1: Options(2).captions = "Total Up"
  68. Options(2).Font = F15: Options(2).clicks = "00"
  69.  
  70. mArray(0) = "Cash"
  71. mArray(1) = "Amer Expr"
  72. mArray(2) = "Mastercar"
  73. mArray(3) = "Discover"
  74. mArray(4) = "Chase"
  75. mArray(5) = "Citi"
  76. mArray(6) = "VISA"
  77. mArray(7) = "Bplus Tab"
  78. menu$ = ""
  79. FOR i = 0 TO 7 'build captions string
  80.     menu$ = menu$ + mArray(i)
  81. Options(3).x = 20: Options(3).y = 250: Options(3).high = 50: Options(3).wide = 150 '1 is mode
  82. Options(3).choices = 7: Options(3).captions = menu$
  83. Options(3).Font = F15: Options(3).clicks = STRING$(Options(1).choices + 1, "0")
  84.  
  85. COLOR &HFFFFFF00, &HFF000000
  86.     DisplayOptions
  87.     getClick mx, my, kh
  88.     IF kh = 27 THEN SYSTEM
  89.     'which button if any was pressed
  90.     FOR o = 1 TO nOptions
  91.         FOR i = 0 TO Options(o).choices
  92.             IF mx > Options(o).x + i * Options(o).wide AND mx < Options(o).x + (i + 1) * Options(o).wide THEN
  93.                 IF my > Options(o).y AND my < Options(o).y + Options(o).high THEN
  94.                     'ok we're in now what?  togggle choice i
  95.                     SELECT CASE o
  96.                         CASE 1
  97.                             Options(2).captions = "Total Up "
  98.                             total! = 0
  99.                             Options(2).clicks = "00"
  100.                             IF MID$(Options(o).clicks, i + 1, 1) = "1" THEN
  101.                                 MID$(Options(o).clicks, i + 1, 1) = "0"
  102.                             ELSE
  103.                                 MID$(Options(o).clicks, i + 1, 1) = "1"
  104.                             END IF
  105.                         CASE 2
  106.                             IF i = 0 THEN
  107.                                 total! = 9.39
  108.                                 FOR j = 1 TO 8
  109.                                     SELECT CASE j
  110.                                         CASE 1: IF MID$(Options(1).clicks, j, 1) = "1" THEN total! = total! + 2.20
  111.                                         CASE 2: IF MID$(Options(1).clicks, j, 1) = "1" THEN total! = total! + 2.40
  112.                                         CASE 3: IF MID$(Options(1).clicks, j, 1) = "1" THEN total! = total! + .40
  113.                                         CASE 4: IF MID$(Options(1).clicks, j, 1) = "1" THEN total! = total! + .70
  114.                                         CASE 5: IF MID$(Options(1).clicks, j, 1) = "1" THEN total! = total! + .90
  115.                                         CASE 6: IF MID$(Options(1).clicks, j, 1) = "1" THEN total! = total! + 1.20
  116.                                         CASE 7: IF MID$(Options(1).clicks, j, 1) = "1" THEN total! = total! + .80
  117.                                         CASE 8: IF MID$(Options(1).clicks, j, 1) = "1" THEN total! = total! + 25.50
  118.                                     END SELECT
  119.                                 NEXT
  120.                                 Options(2).captions = "Total Up  $" + _TRIM$(STR$(total!))
  121.                                 IF total! > 0 THEN Options(2).clicks = "11"
  122.                                 Options(3).clicks = STRING$(Options(3).choices, "0") + "1"
  123.                             END IF
  124.                         CASE 3
  125.                             IF total! > 0 THEN
  126.                                 ttl$ = "Attention Payment Error"
  127.                                 SELECT CASE i
  128.                                     CASE 0: mBox ttl$, "Sorry, your money is no good here. Try Bplus Tab."
  129.                                     CASE 1, 2, 3, 4, 5, 6: mBox ttl$, "Your card has been declined. Try Bplus Tab."
  130.                                     CASE 7: mBox "Payment method approved", "Bplus says Hi, enjoy your pizza!"
  131.                                         Options(2).captions = "Total Up "
  132.                                         total! = 0
  133.                                         Options(2).clicks = "00"
  134.                                         Options(1).clicks = STRING$(8, "0")
  135.                                 END SELECT
  136.                             ELSE
  137.                                 BEEP
  138.                             END IF
  139.                     END SELECT
  140.                 END IF
  141.             END IF
  142.         NEXT
  143.     NEXT
  144.     _LIMIT 60
  145.  
  146. SUB DisplayOptions
  147.     DIM s, i, x1, y1, w, h, clicks$, j, t$
  148.     s = SaveState
  149.     _LIMIT 30
  150.     CLS
  151.     FOR i = 1 TO nOptions '3 option sets to display
  152.         _FONT Options(i).Font
  153.         x1 = Options(i).x: y1 = Options(i).y
  154.         w = Options(i).wide: h = Options(i).high
  155.         clicks$ = Options(i).clicks
  156.         FOR j = 0 TO Options(i).choices
  157.             t$ = _TRIM$(MID$(Options(i).captions, j * 10, 10))
  158.             IF MID$(clicks$, j + 1, 1) = "1" THEN
  159.                 COLOR Black, 0: BoxTitle x1 + j * w, y1, w, h, 3, Skyblue, Gold, t$
  160.             ELSE
  161.                 COLOR LightGray, 0: BoxTitle x1 + j * w, y1, w, h, 3, Black, Gold, t$
  162.             END IF
  163.         NEXT
  164.     NEXT
  165.     RestoreState s
  166.     _DISPLAY
  167.  
  168. SUB BoxTitle (x1, y1, x2, y2, thick, fg AS _UNSIGNED LONG, bg AS _UNSIGNED LONG, title$)
  169.     Box x1, y1, x2, y2, thick, fg, bg
  170.     CenterText x1, y1 + thick, x1 + x2, y1 + y2 + thick, title$
  171.  
  172.  
  173. SUB Box (x, y, wide, high, thick, Kolor AS _UNSIGNED LONG, Trim AS _UNSIGNED LONG)
  174.     DIM i
  175.     LINE (x, y)-STEP(wide, high), Kolor, BF
  176.     FOR i = 0 TO thick - 1
  177.         LINE (x + i, y + i)-STEP(wide - 2 * i, high - 2 * i), Trim, B
  178.     NEXT
  179.  
  180. SUB CenterText (x1, y1, x2, y2, text$)
  181.     DIM xmax, ymax, textlength, xpos, ypos
  182.     text$ = _TRIM$(text$)
  183.     xmax = x2 - x1: ymax = y2 - y1
  184.     textlength = _PRINTWIDTH(text$)
  185.     xpos = (xmax - textlength) / 2
  186.     ypos = (ymax - _FONTHEIGHT) / 2
  187.     _PRINTSTRING (x1 + xpos, y1 + ypos), text$
  188.  
  189. 'getClick returns the mouse x, y position WHEN THE MOUSE WAS RELEASED! or keypress ASC 27 or 32 to 125
  190. '2019-08-06 Test now with new mBox and inputBox procedures
  191. 'found  mBox needed a _KEYCLEAR, how about inputBox?  OK had _KEYCLEAR already
  192. SUB getClick (mx, my, q)
  193.     DIM mb, i
  194.     mb = _MOUSEBUTTON(1)
  195.     WHILE mb
  196.         WHILE _MOUSEINPUT: WEND '<<<<<<<<<<<<<<<<<<<<  clear previous mb
  197.         mb = _MOUSEBUTTON(1)
  198.     WEND
  199.     _KEYCLEAR 'clear previous key presses
  200.     mx = -1: my = -1: q = 0
  201.     DO WHILE mx = -1 AND my = -1
  202.         q = _KEYHIT
  203.         IF q = 27 OR (q > 31 AND q < 126) THEN _KEYCLEAR: EXIT SUB
  204.         i = _MOUSEINPUT: mb = _MOUSEBUTTON(1)
  205.         'IF mb THEN
  206.         DO WHILE mb 'wait for release
  207.             q = _KEYHIT
  208.             IF q = 27 OR (q > 31 AND q < 126) THEN EXIT SUB
  209.             i = _MOUSEINPUT: mb = _MOUSEBUTTON(1): mx = _MOUSEX: my = _MOUSEY
  210.             _LIMIT 1000
  211.         LOOP
  212.         _LIMIT 1000
  213.     LOOP
  214.  
  215.  
  216. FUNCTION SaveState
  217.  
  218.     DIM SS AS SaveStateType, Temp AS SaveStateType, i, O
  219.     'SHARED NSS AS LONG 'Number of Saved States
  220.     'SHARED SaveMem AS _MEM
  221.     IF NOT _MEMEXISTS(SaveMem) THEN
  222.         SaveMem = _MEMNEW(LEN(SS) * 255) 'Save up to 255 save states; More than 255 and we toss an error
  223.         $CHECKING:OFF
  224.         _MEMFILL SaveMem, SaveMem.OFFSET, SaveMem.SIZE, 0 AS _UNSIGNED _BYTE
  225.         $CHECKING:ON
  226.     END IF
  227.  
  228.     'Data to Save
  229.     SS.InUse = -1
  230.     SS.F = _FONT
  231.     SS.DC = _DEFAULTCOLOR
  232.     SS.BG = _BACKGROUNDCOLOR
  233.     SS.D = _DEST
  234.     SS.S = _SOURCE
  235.     SS.Disp = _AUTODISPLAY
  236.     SS.CurX = POS(0)
  237.     SS.CurY = CSRLIN
  238.     FOR i = 1 TO NSS
  239.         O = (i - 1) * LEN(SS)
  240.         _MEMGET SaveMem, SaveMem.OFFSET + O, Temp
  241.         IF Temp.InUse = 0 THEN
  242.             _MEMPUT SaveMem, SaveMem.OFFSET + O, SS
  243.             SaveState = i
  244.             EXIT FUNCTION
  245.         END IF
  246.     NEXT
  247.     _MEMPUT SaveMem, SaveMem.OFFSET + NSS * LEN(SS), SS
  248.     NSS = NSS + 1
  249.     SaveState = NSS
  250.  
  251. SUB RestoreState (WhichOne AS LONG)
  252.     DIM SS AS SaveStateType
  253.     _MEMGET SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
  254.     IF SS.InUse THEN
  255.         SS.InUse = 0 'Let the routine know that we're no longer in use for this handle
  256.         $CHECKING:OFF
  257.         _MEMPUT SaveMem, SaveMem.OFFSET + (WhichOne - 1) * LEN(SS), SS
  258.         $CHECKING:ON
  259.         _FONT SS.F
  260.         COLOR SS.DC, SS.BG
  261.         _DEST SS.D
  262.         _SOURCE SS.S
  263.         IF SS.Disp THEN _AUTODISPLAY ELSE _DISPLAY
  264.         LOCATE SS.CurY, SS.CurX
  265.     END IF
  266.  
  267. 'title$ limit is 57 chars, all lines are 58 chars max, version 2019-08-06
  268. 'THIS SUB NOW NEEDS SUB scnState(restoreTF) for saving and restoring screen settings
  269. SUB mBox (title AS STRING, m AS STRING)
  270.     DIM State AS LONG
  271.     bg = &HFF000040
  272.     fg = &HFF33AAFF
  273.  
  274.     'first screen dimensions and items to restore at exit
  275.     DIM sw AS INTEGER, sh AS INTEGER
  276.     DIM curScrn AS LONG, backScrn AS LONG, mbx AS LONG 'some handles
  277.     DIM ti AS INTEGER, limit AS INTEGER 'ti = text index for t$(), limit is number of chars per line
  278.     DIM i AS INTEGER, j AS INTEGER, ff AS _BIT, add AS _BYTE 'index, flag and
  279.     DIM bxH AS INTEGER, bxW AS INTEGER 'first as cells then as pixels
  280.     DIM mb AS INTEGER, mx AS INTEGER, my AS INTEGER, mi AS INTEGER, grabx AS INTEGER, graby AS INTEGER
  281.     DIM tlx AS INTEGER, tly AS INTEGER 'top left corner of message box
  282.     DIM lastx AS INTEGER, lasty AS INTEGER, t AS STRING, b AS STRING, c AS STRING, tail AS STRING
  283.     DIM d AS STRING, r AS SINGLE, kh AS LONG
  284.  
  285.     'screen and current settings to restore at end ofsub
  286.     'scnState 0
  287.     'try Steve saveState
  288.     State = SaveState
  289.     sw = _WIDTH: sh = _HEIGHT
  290.  
  291.     _KEYCLEAR '<<<<<<<<<<<<<<<<<<<< do i still need this?   YES! 2019-08-06 update!
  292.  
  293.     'screen snapshot
  294.     curScrn = _DEST
  295.     backScrn = _NEWIMAGE(sw, sh, 32)
  296.     _PUTIMAGE , curScrn, backScrn
  297.  
  298.     'setup t() to store strings with ti as index, linit 58 chars per line max, b is for build
  299.     REDIM t(0) AS STRING: ti = 0: limit = 58: b = ""
  300.     FOR i = 1 TO LEN(m)
  301.         c = MID$(m, i, 1)
  302.         'are there any new line signals, CR, LF or both? take CRLF or LFCR as one break but dbl LF or CR means blank line
  303.         SELECT CASE c
  304.             CASE CHR$(13) 'load line
  305.                 IF MID$(m, i + 1, 1) = CHR$(10) THEN i = i + 1
  306.                 t(ti) = b: b = "": ti = ti + 1: REDIM _PRESERVE t(ti) AS STRING
  307.             CASE CHR$(10)
  308.                 IF MID$(m, i + 1, 1) = CHR$(13) THEN i = i + 1
  309.                 t(ti) = b: b = "": ti = ti + 1: REDIM _PRESERVE t(ti)
  310.             CASE ELSE
  311.                 IF c = CHR$(9) THEN c = SPACE$(4): add = 4 ELSE add = 1
  312.                 IF LEN(b) + add > limit THEN
  313.                     tail = "": ff = 0
  314.                     FOR j = LEN(b) TO 1 STEP -1 'backup until find a space, save the tail end for next line
  315.                         d = MID$(b, j, 1)
  316.                         IF d = " " THEN
  317.                             t(ti) = MID$(b, 1, j - 1): b = tail + c: ti = ti + 1: REDIM _PRESERVE t(ti)
  318.                             ff = 1 'found space flag
  319.                             EXIT FOR
  320.                         ELSE
  321.                             tail = d + tail 'the tail grows!
  322.                         END IF
  323.                     NEXT
  324.                     IF ff = 0 THEN 'no break? OK
  325.                         t(ti) = b: b = c: ti = ti + 1: REDIM _PRESERVE t(ti)
  326.                     END IF
  327.                 ELSE
  328.                     b = b + c 'just keep building the line
  329.                 END IF
  330.         END SELECT
  331.     NEXT
  332.     t(ti) = b
  333.     bxH = ti + 3: bxW = limit + 2
  334.  
  335.     'draw message box
  336.     mbx = _NEWIMAGE(60 * 8, (bxH + 1) * 16, 32)
  337.     _DEST mbx
  338.     COLOR _RGB32(128, 0, 0), _RGB32(225, 225, 255)
  339.     LOCATE 1, 1: PRINT LEFT$(SPACE$((bxW - LEN(title) - 3) / 2) + title + SPACE$(bxW), bxW)
  340.     COLOR _RGB32(225, 225, 255), _RGB32(200, 0, 0)
  341.     LOCATE 1, bxW - 2: PRINT " X "
  342.     COLOR fg, bg
  343.     LOCATE 2, 1: PRINT SPACE$(bxW);
  344.     FOR r = 0 TO ti
  345.         LOCATE 1 + r + 2, 1: PRINT LEFT$(" " + t(r) + SPACE$(bxW), bxW);
  346.     NEXT
  347.     LOCATE 1 + bxH, 1: PRINT SPACE$(limit + 2);
  348.  
  349.     'now for the action
  350.     _DEST curScrn
  351.  
  352.     'convert to pixels the top left corner of box at moment
  353.     bxW = bxW * 8: bxH = bxH * 16
  354.     tlx = (sw - bxW) / 2: tly = (sh - bxH) / 2
  355.     lastx = tlx: lasty = tly
  356.     'now allow user to move it around or just read it
  357.     WHILE 1
  358.         CLS
  359.         _PUTIMAGE , backScrn
  360.         _PUTIMAGE (tlx, tly), mbx, curScrn
  361.         _DISPLAY
  362.         WHILE _MOUSEINPUT: WEND
  363.         mx = _MOUSEX: my = _MOUSEY: mb = _MOUSEBUTTON(1)
  364.         IF mb THEN
  365.             IF mx >= tlx AND mx <= tlx + bxW AND my >= tly AND my <= tly + 16 THEN 'mouse down on title bar
  366.                 IF mx >= tlx + bxW - 24 THEN EXIT WHILE
  367.                 grabx = mx - tlx: graby = my - tly
  368.                 DO WHILE mb 'wait for release
  369.                     mi = _MOUSEINPUT: mb = _MOUSEBUTTON(1)
  370.                     mx = _MOUSEX: my = _MOUSEY
  371.                     IF mx - grabx >= 0 AND mx - grabx <= sw - bxW AND my - graby >= 0 AND my - graby <= sh - bxH THEN
  372.                         'attempt to speed up with less updates
  373.                         IF ((lastx - (mx - grabx)) ^ 2 + (lasty - (my - graby)) ^ 2) ^ .5 > 10 THEN
  374.                             tlx = mx - grabx: tly = my - graby
  375.                             CLS
  376.                             _PUTIMAGE , backScrn
  377.                             _PUTIMAGE (tlx, tly), mbx, curScrn
  378.                             lastx = tlx: lasty = tly
  379.                             _DISPLAY
  380.                         END IF
  381.                     END IF
  382.                     _LIMIT 400
  383.                 LOOP
  384.             END IF
  385.         END IF
  386.         kh = _KEYHIT
  387.         IF kh = 27 OR kh = 13 OR kh = 32 THEN EXIT WHILE
  388.         _LIMIT 400
  389.     WEND
  390.  
  391.     'put things back
  392.     COLOR _RGB32(255, 255, 255), _RGB32(0, 0, 0): CLS '
  393.     _PUTIMAGE , backScrn
  394.     _DISPLAY
  395.     _FREEIMAGE backScrn
  396.     _FREEIMAGE mbx
  397.  
  398.     RestoreState State ' testing Steve's RestoreState
  399.     'scnState 1 'Thanks Steve McNeill
  400.  
  401.  
  402.  
  403. ' try out Steve's saveState and RestoreState procedures inside mBox
  404.  
  405. '' for saving and restoring screen settins
  406. 'SUB scnState (restoreTF AS INTEGER) 'Thanks Steve McNeill
  407. '    STATIC Font AS LONG, DefaultColor AS _UNSIGNED LONG, BackGroundColor AS _UNSIGNED LONG, Dest AS LONG, Source AS LONG
  408. '    STATIC row AS INTEGER, col AS INTEGER, autodisplay AS INTEGER, mb AS INTEGER
  409. '    IF restoreTF THEN
  410. '        _FONT Font
  411. '        COLOR DefaultColor, BackGroundColor
  412. '        _DEST Dest
  413. '        _SOURCE Source
  414. '        LOCATE row, col
  415. '        IF autodisplay THEN _AUTODISPLAY ELSE _DISPLAY
  416. '        _KEYCLEAR
  417. '        WHILE _MOUSEINPUT: WEND 'clear mouse clicks
  418. '        mb = _MOUSEBUTTON(1)
  419. '        IF mb THEN
  420. '            DO
  421. '                WHILE _MOUSEINPUT: WEND
  422. '                mb = _MOUSEBUTTON(1)
  423. '                _LIMIT 100
  424. '            LOOP UNTIL mb = 0
  425. '        END IF
  426. '    ELSE
  427. '        Font = _FONT: DefaultColor = _DEFAULTCOLOR: BackGroundColor = _BACKGROUNDCOLOR
  428. '        Dest = _DEST: Source = _SOURCE
  429. '        row = CSRLIN: col = POS(0): autodisplay = _AUTODISPLAY
  430. '    END IF
  431. 'END SUB
  432.  

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: A quick selection menu
« Reply #12 on: August 12, 2019, 05:09:43 pm »
Hey but your cashbox doesn't let use any payment except Bplus Tab that double the price of pizza for commitment!
:-)
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: A quick selection menu
« Reply #13 on: August 12, 2019, 05:26:03 pm »
Hey but your cashbox doesn't let use any payment except Bplus Tab that double the price of pizza for commitment!
:-)

Well I hope that isn't a complaint! :D

Hey TempodiBasic, do you have Linux and if so does the messageBox work OK? Can you grab it by the title bar and drag it around the screen?

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: A quick selection menu
« Reply #14 on: August 12, 2019, 07:58:45 pm »
OK I'll do in my VM Virtualbox!
Programming isn't difficult, only it's  consuming time and coffee