Author Topic: Wouldn't it be nice if TYPE could be used with STATIC? Oh it can! Thanks BPlus!  (Read 2271 times)

0 Members and 1 Guest are viewing this topic.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Maybe it can, and just have't figured out how, but doing a flow-through library routine, I just had to define as STATIC 30 variables. I used 3 types for these, so it would have been nie to be able to do something like...

STATIC margin, scrollbar, cursor

instead of what is required...

STATIC margin.left, margin.right, margin.top, margin.bottom, scrollbar.top, scrollbar.bottom, scrollbar.index

etc., etc, etc.

It is neat that you can use TYPE in subs with QB64. I don't believe that was possible in QBasic, but it would be cool to be able to use TYPE in a STATIC statement, to cut down on typing in so many static variables in a sub.

Pete
« Last Edit: October 29, 2020, 06:42:27 pm by Pete »
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Wouldn't it be nice if TYPE could be used with STATIC?
« Reply #1 on: October 29, 2020, 11:15:28 am »
Ah, I don't use STATIC much (I prefer SHARE at module level and being careful with name), STATIC doesn't work for UDT's?

No it works!
Code: QB64: [Select]
  1. TYPE xy
  2.     x AS INTEGER
  3.     y AS INTEGER
  4.  
  5. FOR i = 1 TO 20
  6.     foo irnd%(-10, 10), irnd%(-100, 100), lowX, lowY
  7.     PRINT i, lowX, lowY
  8.  
  9.  
  10. SUB foo (a, b, xOut, yOut)
  11.     STATIC lowAB AS xy, beenHere
  12.     IF beenHere = 0 THEN
  13.         lowAB.x = 1000: lowAB.y = 1000
  14.         beenHere = 1
  15.     END IF
  16.     IF a < lowAB.x THEN lowAB.x = a
  17.     IF b < lowAB.y THEN lowAB.y = b
  18.     xOut = lowAB.x
  19.     yOut = lowAB.y
  20.  
  21. FUNCTION irnd% (n1, n2) 'return an integer between 2 numbers
  22.     DIM l%, h%
  23.     IF n1 > n2 THEN l% = n2: h% = n1 ELSE l% = n1: h% = n2
  24.     irnd% = INT(RND * (h% - l% + 1)) + l%
  25.  
  26.  


Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Wouldn't it be nice if TYPE could be used with STATIC?
« Reply #2 on: October 29, 2020, 05:28:52 pm »
That's a more complicated use of TYPE than I use. Actually, up until this year, I never used TYPE.

So I looked over your code example, but I must have goofed somewhere when applying it to mine. Wait, I'm back. Woohoo. I just goofed on forgetting to remove one element.

So the first one works, by explicitly placing each variable in the STATIC statements, and now, thanks to your helpful example, the second one works, too!

Scroll bar demo library. This code does not use or make files.

Code: QB64: [Select]
  1. ' MAIN DEMO -----------------------------------------------------------------
  2. DIM SHARED debug%
  3. DO: PRINT "Input screen width: 60 - 140, blank for default demo or -1 for debug mode: ";: INPUT screen_width%
  4.     IF screen_width% = -1 THEN debug% = -1: m_top% = 1: m_bottom% = 5: m_left% = 124: m_right% = 8: screen_width% = 150: text_lines% = 99: GOTO make_fake_text ' Debug mode.
  5.     IF screen_width% = 0 THEN m_top% = 0: m_bottom% = 0: m_left% = 10: m_right% = 12: screen_width% = 80: text_lines% = 99: GOTO make_fake_text ' Use defaults for demo.
  6.     IF screen_width% >= 60 AND screen_width% <= 140 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  7. DO: PRINT "Input number of text entries 10 - 99: ";: INPUT text_lines%
  8.     IF text_lines% >= 10 AND text_lines% <= 99 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  9. DO: PRINT "Input margin top 0 to 10: ";: INPUT m_top%
  10.     IF m_top% >= 0 AND m_top% <= 10 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  11. DO: PRINT "Input margin bottom 0 to 10: ";: INPUT m_bottom%
  12.     IF m_bottom% >= 0 AND m_bottom% <= 10 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  13. DO: PRINT "Input margin left 0 to 20: ";: INPUT m_left%
  14.     IF m_left% >= 0 AND m_left% <= 20 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  15. DO: PRINT "Input margin right: 2 to 20: ";: INPUT m_right%
  16.     IF m_right% >= 2 AND m_right% <= 20 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  17.  
  18. make_fake_text:
  19. CLS: REDIM mytext$(text_lines%)
  20. FOR i% = 1 TO text_lines%
  21.     FOR j% = 1 TO screen_width% - (m_left% + m_right%) - 3
  22.         k% = (RND * 24) + 97 + 8
  23.         IF k% > 122 THEN
  24.             IF RIGHT$(mytext$(i%), 1) <> " " AND LEN(mytext$(i%)) THEN a$ = " " ELSE a$ = CHR$((RND * 24) + 97)
  25.         ELSE
  26.             a$ = CHR$(k%)
  27.         END IF
  28.         mytext$(i%) = mytext$(i%) + a$
  29.     NEXT j%
  30.     mytext$(i%) = STRING$(2 - LEN(LTRIM$(STR$(i%))), "0") + LTRIM$(STR$(i%)) + " " + mytext$(i%)
  31. NEXT i%
  32.  
  33. WIDTH screen_width%, 25
  34. IF screen_width% > 90 THEN _SCREENMOVE 0, 0
  35.  
  36.     CALL scrollbar_library(mytext$(), text_lines%, m_top%, m_bottom%, m_left%, m_right%, text_row%, text_scrolled%)
  37. END ' -----------------------------------------------------------------------
  38.  
  39. SUB scrollbar_library (x$(), noe%, margin.t, margin.b, margin.l, margin.r, row%, scr%)
  40.     STATIC initiate_scrb%
  41.     STATIC scrn.w, scrn.h
  42.     STATIC scrb.t, scrb.b, scrb.l, scrb.d, scrb.x, scrb.i, scrb.h, scrb.s
  43.     STATIC cursor.find, cursor.scbrrow, cursor.scbrcol, cursor.holdscr, cursor.holdrow, cursor.holdscrbx
  44.     STATIC page.h%, delay_on!, mb.l, mb.dragon, mb.drag
  45.  
  46.     IF initiate_scrb% = 0 THEN
  47.         GOSUB getvar_setscrn
  48.         initiate_scrb% = -1
  49.         GOSUB displayscrn: GOSUB makescrb
  50.     END IF
  51.  
  52.     IF debug% THEN GOSUB analize ' Debug only.
  53.  
  54.     GOSUB getkey
  55.  
  56.     EXIT SUB
  57.  
  58.     getvar_setscrn:
  59.  
  60.     TYPE margin
  61.         t AS INTEGER
  62.         b AS INTEGER
  63.         l AS INTEGER
  64.         r AS INTEGER
  65.     END TYPE
  66.  
  67.     TYPE scrb
  68.         t AS INTEGER
  69.         b AS INTEGER
  70.         l AS INTEGER
  71.         x AS INTEGER
  72.         i AS INTEGER
  73.         d AS INTEGER
  74.         h AS INTEGER
  75.         s AS INTEGER
  76.     END TYPE
  77.  
  78.     TYPE cursor
  79.         find AS INTEGER
  80.         scbrrow AS INTEGER ' row% + scr%
  81.         scbrcol AS INTEGER ' POS(0)
  82.         holdscr AS INTEGER ' Holds scr%
  83.         holdrow AS INTEGER ' Holds row%
  84.         holdscrbx AS INTEGER ' Holds scrb.x
  85.     END TYPE
  86.  
  87.     TYPE mb
  88.         l AS INTEGER
  89.         r AS INTEGER
  90.         m AS INTEGER
  91.         drag AS INTEGER
  92.         dragon AS INTEGER
  93.     END TYPE
  94.  
  95.     scrn.w = _WIDTH
  96.     scrn.h = _HEIGHT
  97.     scrb.x = 0 ' Relative position of the scrollbar cursor from top of scrb.h. 0 Off / 1 to
  98.     IF row% = 0 THEN row% = 1
  99.  
  100.     ' Calculations
  101.     page.w% = scrn.w - (margin.l + margin.r)
  102.     page.h% = scrn.h - (margin.t + margin.b)
  103.     scrb.t = margin.t + 1
  104.     scrb.b = margin.t + page.h%
  105.     scrb.l = margin.l + page.w% + 2
  106.     scrb.d = scrb.b - scrb.t + 1
  107.     scrb.h = scrb.b - scrb.t - 1 ' Max. vertical scroll. Bar minus the top and bottom arrow symbols.
  108.  
  109.     LOCATE margin.t + row%, margin.l + 1, 1
  110.     cursor.scbrrow = row% + scr%: cursor.scbrcol = POS(0)
  111.     RETURN
  112.  
  113.     displayscrn:
  114.     yy% = CSRLIN: xx% = POS(0)
  115.     LOCATE , , 0: ' Cursor hide.
  116.     j% = 0
  117.     DO ' page.h% determines how mnay rows of text are displayed.
  118.         j% = j% + 1
  119.         LOCATE margin.t + j%, margin.l + 1
  120.         PRINT x$(scr% + j%);
  121.         IF j% = page.h% OR j% = noe% THEN EXIT DO
  122.     LOOP
  123.     LOCATE yy%, xx%
  124.     IF cursor.find THEN
  125.         cursor.find = 0
  126.         IF cursor.scbrrow > scr% AND cursor.scbrrow <= scr% + page.h% THEN
  127.             LOCATE margin.t + cursor.scbrrow - scr%, cursor.scbrcol, 1 ' Cursor show.
  128.         END IF
  129.     ELSE
  130.         LOCATE , , 1 ' Show cursor.
  131.     END IF
  132.     RETURN
  133.  
  134.     makescrb:
  135.     yy% = CSRLIN: xx% = POS(0)
  136.     LOCATE scrb.t, scrb.l
  137.     COLOR 0, 7
  138.     PRINT CHR$(24);
  139.     COLOR 7, 0
  140.     FOR i% = 1 TO scrb.h
  141.         LOCATE scrb.t + i%, scrb.l
  142.         PRINT CHR$(177);
  143.     NEXT i%
  144.     LOCATE scrb.b, scrb.l
  145.     COLOR 0, 7
  146.     PRINT CHR$(25);
  147.     COLOR 7, 0
  148.  
  149.     IF noe% > scrb.h + 2 THEN
  150.         scrb.s = (scrb.h + 1) * 2 - noe%
  151.         IF scrb.s <= 0 THEN scrb.s = 1
  152.         FOR i% = 1 TO scrb.s
  153.             LOCATE scrb.t + i% + scrb.x, scrb.l
  154.             COLOR 1, 0
  155.             PRINT CHR$(176); ' Scrollbar index cursor.
  156.         NEXT
  157.         COLOR 7, 0
  158.     END IF
  159.     LOCATE yy%, xx%
  160.     RETURN
  161.  
  162.     getkey:
  163.     _LIMIT 60 ' Can be reduced or removed. Since this is a flow-through library, this limit will affect the entire program.
  164.     row% = CSRLIN - margin.t
  165.     IF b$ = "" THEN b$ = INKEY$ ' Since library is flow-through b$ might be initiated by another routine.
  166.     IF LEN(b$) THEN
  167.         SELECT CASE b$
  168.             CASE CHR$(0) + "H"
  169.                 GOSUB backtocursor
  170.                 IF row% + scr% > 0 THEN
  171.                     IF row% = 1 THEN
  172.                         IF scr% > 0 THEN
  173.                             scr% = scr% - 1
  174.                             GOSUB displayscrn
  175.                         END IF
  176.                     ELSE
  177.                         row% = row% - 1
  178.                     END IF
  179.                     LOCATE row% + margin.t, margin.l + 1
  180.                     GOSUB getcurrow
  181.                 END IF
  182.             CASE CHR$(0) + "P"
  183.                 GOSUB backtocursor
  184.                 IF row% + scr% < noe% THEN
  185.                     IF row% = page.h% THEN
  186.                         scr% = scr% + 1
  187.                         GOSUB displayscrn
  188.                     ELSE
  189.                         row% = row% + 1
  190.                     END IF
  191.                     LOCATE row% + margin.t, margin.l + 1
  192.                     GOSUB getcurrow
  193.                 END IF
  194.             CASE CHR$(9)
  195.                 RUN
  196.             CASE CHR$(27)
  197.                 SYSTEM
  198.         END SELECT
  199.  
  200.         ' Reverse algorithm. Not needed for this routine. scrb.x = scrb.i / ((noe% - scrb.d) / (scrb.h - scrb.s))
  201.  
  202.         IF row% + scr% >= INT((scrb.x + 1) * ((noe% - scrb.d) / (scrb.h - scrb.s))) + page.h% THEN
  203.             scrb.x = scrb.x + 1
  204.  
  205.             GOSUB makescrb
  206.  
  207.             scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  208.         ELSEIF row% + scr% <= scrb.i THEN
  209.             scrb.x = scrb.x - 1
  210.  
  211.             GOSUB makescrb
  212.  
  213.             scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  214.         END IF
  215.         b$ = ""
  216.     END IF
  217.  
  218.     IF delay_on! THEN ' Scrollbar delay.
  219.         _DELAY delay_on!
  220.         delay_on! = 0 ' Toggle off.
  221.     END IF
  222.  
  223.  
  224.     mb.l = _MOUSEBUTTON(1)
  225.  
  226.     IF mb.l THEN
  227.         mx% = _MOUSEX ' Mouse column.
  228.         my% = _MOUSEY ' Mouse row%.
  229.  
  230.         IF mx% = scrb.l AND scrb.s AND my% >= scrb.t AND my% <= scrb.b OR mb.dragon THEN ' Mouse on scrollbar or doing a bar cursor drag.
  231.             SELECT CASE mb.dragon
  232.                 CASE 0
  233.                     IF my% = scrb.t AND scrb.x > 0 OR my% = scrb.b AND scrb.x + scrb.s < scrb.h THEN ' Mouse on a scrollbar arrow.
  234.                         IF my% = scrb.t THEN scrb.x = scrb.x - 1 ELSE scrb.x = scrb.x + 1 ' Top or bottom arrow.
  235.                         delay_on! = .15
  236.                         scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  237.                         scr% = scrb.i
  238.                         cursor.find = -1
  239.  
  240.                         GOSUB displayscrn: GOSUB makescrb
  241.  
  242.                     ELSEIF my% - (scrb.t + 1) >= scrb.x AND my% - (scrb.t + 1) <= scrb.x + scrb.s - 1 THEN ' Mouse on scrollbar cursor.
  243.                         mb.drag = my% - (scrb.t + 1)
  244.                         mb.dragon = -1
  245.                     ELSEIF my% > scrb.t AND my% < scrb.b OR mb.dragon THEN ' Mouse on scrollbar between scrollbar arrow and cursor.
  246.                         IF my% - (scrb.t + 1) < scrb.x THEN
  247.                             scrb.x = my% - (scrb.t + 1)
  248.                         ELSE
  249.                             scrb.x = my% - (scrb.t + 1) - (scrb.s - 1) ' The second argument compensates for large scroll cursors with fewer elements to scroll. Example: 15 elements in a 10 height scrollbar has a 3-space scrollbar cursor.
  250.                         END IF
  251.                         delay_on! = .15
  252.                         scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  253.                         scr% = scrb.i
  254.                         cursor.find = -1
  255.  
  256.                         GOSUB displayscrn: GOSUB makescrb
  257.  
  258.                     END IF
  259.  
  260.                 CASE ELSE ' Scrollbar cursor drag.
  261.                     IF my% - (scrb.t + 1) < mb.drag AND my% - (scrb.t + 1) - (mb.drag - scrb.x) >= 0 THEN
  262.                         i% = mb.drag - scrb.x
  263.                         scrb.x = my% - (scrb.t + 1) - i%
  264.                         mb.drag = scrb.x + i%
  265.                         scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  266.                         scr% = scrb.i
  267.                         cursor.find = -1
  268.  
  269.                         GOSUB displayscrn: GOSUB makescrb
  270.  
  271.                     ELSEIF my% - (scrb.t + 1) > mb.drag AND my% - (scrb.t + 1) + (scrb.x - mb.drag) < scrb.h - (scrb.s - 1) THEN
  272.                         i% = scrb.x - mb.drag
  273.                         scrb.x = my% - (scrb.t + 1) + i%
  274.                         mb.drag = scrb.x - i%
  275.                         scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  276.                         scr% = scrb.i
  277.                         cursor.find = -1
  278.  
  279.                         GOSUB displayscrn: GOSUB makescrb
  280.                     ELSE
  281.                         i% = my% - (scrb.t + 1)
  282.                         IF i% >= scrb.t AND i% <= scrb.h THEN mb.drag = my% - (scrb.t + 1)
  283.                     END IF
  284.             END SELECT
  285.  
  286.         ELSEIF my% >= margin.t + 1 AND my% <= margin.t + page.h% THEN
  287.             IF mx% >= margin.l + 1 AND mx% <= scrn.w - margin.r THEN
  288.                 LOCATE my%, mx%, 1 ' Locate by left mouse click and show cursor.
  289.                 GOSUB getcurrow
  290.             END IF
  291.         END IF
  292.     ELSE
  293.         mb.drag = 0: mb.dragon = 0
  294.     END IF
  295.     RETURN
  296.  
  297.     getcurrow:
  298.     row% = CSRLIN - margin.t
  299.     cursor.scbrrow = row% + scr%
  300.     cursor.scbrcol = POS(0)
  301.     cursor.holdscr = scr%
  302.     cursor.holdrow = row%
  303.     cursor.holdscrbx = scrb.x
  304.     RETURN
  305.  
  306.     backtocursor:
  307.     IF cursor.scbrrow > scr% AND cursor.scbrrow <= scr% + page.h% THEN
  308.         ' Display region does not contain cursor. Do nothing.
  309.     ELSE ' Display region contains the cursor.
  310.         scr% = cursor.holdscr
  311.         row% = cursor.holdrow
  312.         scrb.x = cursor.holdscrbx
  313.         scrb.i = scr%
  314.         GOSUB makescrb
  315.         GOSUB displayscrn
  316.     END IF
  317.     RETURN
  318.  
  319.     analize:
  320.     ss% = CSRLIN: tt% = POS(0)
  321.     LOCATE 2, 1
  322.     PRINT " initiate_scrb% ="; initiate_scrb%
  323.     PRINT " scrn.w ="; scrn.w; " scrn.h ="; scrn.h; scrb.s; "     "
  324.     PRINT " margin.t ="; margin.t; " margin.b ="; margin.b; " margin.l ="; margin.l; " margin.r ="; margin.r; scrb.s; "     "
  325.     PRINT " scrb.t ="; scrb.t; " scrb.b ="; scrb.b; " scrb.l ="; scrb.l; " scrb.d ="; scrb.d; " scrb.x = "; scrb.x; " scrb.i ="; scrb.i; " scrb.h ="; scrb.h; " scrb.s ="; scrb.s; "     "
  326.     PRINT " cursor.find ="; cursor.find; " cursor.scbrrow ="; cursor.scbrrow; " cursor.scbrcol = "; cursor.scbrcol; scrb.s; "     "
  327.     PRINT " cursor.holdscr ="; cursor.holdscr; " cursor.holdrow ="; cursor.holdrow; " cursor.holdscrbx ="; cursor.holdscrbx
  328.     PRINT " page.h% ="; page.h%; " noe% = "; noe%; " delay_on! ="; delay_on!; " row% = "; row%; " scr% ="; scr%; " mx% ="; mx%; " my% ="; my%; " mb.l ="; mb.l; " mb.dragon ="; mb.dragon; " mb.drag ="; mb.drag; "     "
  329.     LOCATE ss%, tt%
  330.     _DELAY .05
  331.     RETURN
  332.  
  333.     $IF  THEN
  334.         Notes: DIM SHARED variables for a GLOBAL format option.---------------
  335.         DIM SHARED initiate_scrb%
  336.         DIM SHARED scrn.w, scrn.h
  337.         DIM SHARED margin.t, margin.b, margin.l, margin.r
  338.         DIM SHARED scrb.t, scrb.b, scrb.l, scrb.d, scrb.x, scrb.i, scrb.h, scrb.s
  339.         DIM SHARED cursor.find, cursor.scbrrow, cursor.scbrcol, cursor.holdscr, cursor.holdrow, cursor.holdscrbx
  340.         DIM SHARED page.h%, noe%, delay_on!, row%, scr%, mb.l, mb.dragon, mb.drag
  341.     $END IF
  342.  

Now the same code but trying to get UDT in STATIC, unsuccessfully...

Code: QB64: [Select]
  1. ' MAIN DEMO -----------------------------------------------------------------
  2. DIM SHARED debug%
  3. DO: PRINT "Input screen width: 60 - 140, blank for default demo or -1 for debug mode: ";: INPUT screen_width%
  4.     IF screen_width% = -1 THEN debug% = -1: m_top% = 1: m_bottom% = 5: m_left% = 124: m_right% = 8: screen_width% = 150: text_lines% = 99: GOTO make_fake_text ' Debug mode.
  5.     IF screen_width% = 0 THEN m_top% = 0: m_bottom% = 0: m_left% = 10: m_right% = 12: screen_width% = 80: text_lines% = 99: GOTO make_fake_text ' Use defaults for demo.
  6.     IF screen_width% >= 60 AND screen_width% <= 140 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  7. DO: PRINT "Input number of text entries 10 - 99: ";: INPUT text_lines%
  8.     IF text_lines% >= 10 AND text_lines% <= 99 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  9. DO: PRINT "Input margin top 0 to 10: ";: INPUT m_top%
  10.     IF m_top% >= 0 AND m_top% <= 10 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  11. DO: PRINT "Input margin bottom 0 to 10: ";: INPUT m_bottom%
  12.     IF m_bottom% >= 0 AND m_bottom% <= 10 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  13. DO: PRINT "Input margin left 0 to 20: ";: INPUT m_left%
  14.     IF m_left% >= 0 AND m_left% <= 20 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  15. DO: PRINT "Input margin right: 2 to 20: ";: INPUT m_right%
  16.     IF m_right% >= 2 AND m_right% <= 20 THEN EXIT DO ELSE PRINT: PRINT "Redo...": PRINT
  17.  
  18. make_fake_text:
  19. CLS: REDIM mytext$(text_lines%)
  20. FOR i% = 1 TO text_lines%
  21.     FOR j% = 1 TO screen_width% - (m_left% + m_right%) - 3
  22.         k% = (RND * 24) + 97 + 8
  23.         IF k% > 122 THEN
  24.             IF RIGHT$(mytext$(i%), 1) <> " " AND LEN(mytext$(i%)) THEN a$ = " " ELSE a$ = CHR$((RND * 24) + 97)
  25.         ELSE
  26.             a$ = CHR$(k%)
  27.         END IF
  28.         mytext$(i%) = mytext$(i%) + a$
  29.     NEXT j%
  30.     mytext$(i%) = STRING$(2 - LEN(LTRIM$(STR$(i%))), "0") + LTRIM$(STR$(i%)) + " " + mytext$(i%)
  31. NEXT i%
  32.  
  33. WIDTH screen_width%, 25
  34. IF screen_width% > 90 THEN _SCREENMOVE 0, 0
  35.  
  36.     CALL scrollbar_library(mytext$(), text_lines%, m_top%, m_bottom%, m_left%, m_right%, text_row%, text_scrolled%)
  37. END ' -----------------------------------------------------------------------
  38.  
  39. SUB scrollbar_library (x$(), noe%, margin.t, margin.b, margin.l, margin.r, row%, scr%)
  40.  
  41.     STATIC initiate_scrb%, debug%, page.h%, delay_on!
  42.     STATIC scrn AS my_scrn, scrb AS my_scrb, cursor AS my_cursor, mb AS my_mb
  43.  
  44.     IF initiate_scrb% = 0 THEN
  45.         debug% = 0 ' Set to non-zero for debug data.
  46.         GOSUB getvar_setscrn
  47.         initiate_scrb% = -1
  48.         GOSUB displayscrn: GOSUB makescrb
  49.     END IF
  50.  
  51.     IF debug% THEN GOSUB analize ' Debug only.
  52.  
  53.     GOSUB getkey
  54.  
  55.     EXIT SUB
  56.  
  57.     getvar_setscrn:
  58.  
  59.     TYPE my_scrn
  60.         w AS INTEGER
  61.         h AS INTEGER
  62.     END TYPE
  63.  
  64.     TYPE my_margin
  65.         t AS INTEGER
  66.         b AS INTEGER
  67.         l AS INTEGER
  68.         r AS INTEGER
  69.     END TYPE
  70.  
  71.     TYPE my_scrb
  72.         t AS INTEGER
  73.         b AS INTEGER
  74.         l AS INTEGER
  75.         x AS INTEGER
  76.         i AS INTEGER
  77.         d AS INTEGER
  78.         h AS INTEGER
  79.         s AS INTEGER
  80.     END TYPE
  81.  
  82.     TYPE my_cursor
  83.         find AS INTEGER
  84.         scbrrow AS INTEGER ' row% + scr%
  85.         scbrcol AS INTEGER ' POS(0)
  86.         holdscr AS INTEGER ' Holds scr%
  87.         holdrow AS INTEGER ' Holds row%
  88.         holdscrbx AS INTEGER ' Holds scrb.x
  89.     END TYPE
  90.  
  91.     TYPE my_mb
  92.         l AS INTEGER
  93.         r AS INTEGER
  94.         m AS INTEGER
  95.         drag AS INTEGER
  96.         dragon AS INTEGER
  97.     END TYPE
  98.  
  99.     scrn.w = _WIDTH
  100.     scrn.h = _HEIGHT
  101.     scrb.x = 0 ' Relative position of the scrollbar cursor from top of scrb.h. 0 Off / 1 to
  102.     IF row% = 0 THEN row% = 1
  103.  
  104.     ' Calculations
  105.     page.w% = scrn.w - (margin.l + margin.r)
  106.     page.h% = scrn.h - (margin.t + margin.b)
  107.     scrb.t = margin.t + 1
  108.     scrb.b = margin.t + page.h%
  109.     scrb.l = margin.l + page.w% + 2
  110.     scrb.d = scrb.b - scrb.t + 1
  111.     scrb.h = scrb.b - scrb.t - 1 ' Max. vertical scroll. Bar minus the top and bottom arrow symbols.
  112.  
  113.     LOCATE margin.t + row%, margin.l + 1, 1
  114.     cursor.scbrrow = row% + scr%: cursor.scbrcol = POS(0)
  115.     RETURN
  116.  
  117.     displayscrn:
  118.     yy% = CSRLIN: xx% = POS(0)
  119.     LOCATE , , 0: ' Cursor hide.
  120.     j% = 0
  121.     DO ' page.h% determines how mnay rows of text are displayed.
  122.         j% = j% + 1
  123.         LOCATE margin.t + j%, margin.l + 1
  124.         PRINT x$(scr% + j%);
  125.         IF j% = page.h% OR j% = noe% THEN EXIT DO
  126.     LOOP
  127.     LOCATE yy%, xx%
  128.     IF cursor.find THEN
  129.         cursor.find = 0
  130.         IF cursor.scbrrow > scr% AND cursor.scbrrow <= scr% + page.h% THEN
  131.             LOCATE margin.t + cursor.scbrrow - scr%, cursor.scbrcol, 1 ' Cursor show.
  132.         END IF
  133.     ELSE
  134.         LOCATE , , 1 ' Show cursor.
  135.     END IF
  136.     RETURN
  137.  
  138.     makescrb:
  139.     yy% = CSRLIN: xx% = POS(0)
  140.     LOCATE scrb.t, scrb.l
  141.     COLOR 0, 7
  142.     PRINT CHR$(24);
  143.     COLOR 7, 0
  144.     FOR i% = 1 TO scrb.h
  145.         LOCATE scrb.t + i%, scrb.l
  146.         PRINT CHR$(177);
  147.     NEXT i%
  148.     LOCATE scrb.b, scrb.l
  149.     COLOR 0, 7
  150.     PRINT CHR$(25);
  151.     COLOR 7, 0
  152.  
  153.     IF noe% > scrb.h + 2 THEN
  154.         scrb.s = (scrb.h + 1) * 2 - noe%
  155.         IF scrb.s <= 0 THEN scrb.s = 1
  156.         FOR i% = 1 TO scrb.s
  157.             LOCATE scrb.t + i% + scrb.x, scrb.l
  158.             COLOR 1, 0
  159.             PRINT CHR$(176); ' Scrollbar index cursor.
  160.         NEXT
  161.         COLOR 7, 0
  162.     END IF
  163.     LOCATE yy%, xx%
  164.     RETURN
  165.  
  166.     getkey:
  167.     _LIMIT 60 ' Can be reduced or removed. Since this is a flow-through library, this limit will affect the entire program.
  168.     row% = CSRLIN - margin.t
  169.     IF b$ = "" THEN b$ = INKEY$ ' Since library is flow-through b$ might be initiated by another routine.
  170.     IF LEN(b$) THEN
  171.         SELECT CASE b$
  172.             CASE CHR$(0) + "H"
  173.                 GOSUB backtocursor
  174.                 IF row% + scr% > 0 THEN
  175.                     IF row% = 1 THEN
  176.                         IF scr% > 0 THEN
  177.                             scr% = scr% - 1
  178.                             GOSUB displayscrn
  179.                         END IF
  180.                     ELSE
  181.                         row% = row% - 1
  182.                     END IF
  183.                     LOCATE row% + margin.t, margin.l + 1
  184.                     GOSUB getcurrow
  185.                 END IF
  186.             CASE CHR$(0) + "P"
  187.                 GOSUB backtocursor
  188.                 IF row% + scr% < noe% THEN
  189.                     IF row% = page.h% THEN
  190.                         scr% = scr% + 1
  191.                         GOSUB displayscrn
  192.                     ELSE
  193.                         row% = row% + 1
  194.                     END IF
  195.                     LOCATE row% + margin.t, margin.l + 1
  196.                     GOSUB getcurrow
  197.                 END IF
  198.             CASE CHR$(9)
  199.                 RUN
  200.             CASE CHR$(27)
  201.                 SYSTEM
  202.         END SELECT
  203.  
  204.         ' Reverse algorithm. Not needed for this routine. scrb.x = scrb.i / ((noe% - scrb.d) / (scrb.h - scrb.s))
  205.  
  206.         IF row% + scr% >= INT((scrb.x + 1) * ((noe% - scrb.d) / (scrb.h - scrb.s))) + page.h% THEN
  207.             scrb.x = scrb.x + 1
  208.  
  209.             GOSUB makescrb
  210.  
  211.             scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  212.         ELSEIF row% + scr% <= scrb.i THEN
  213.             scrb.x = scrb.x - 1
  214.  
  215.             GOSUB makescrb
  216.  
  217.             scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  218.         END IF
  219.         b$ = ""
  220.     END IF
  221.  
  222.     IF delay_on! THEN ' Scrollbar delay.
  223.         _DELAY delay_on!
  224.         delay_on! = 0 ' Toggle off.
  225.     END IF
  226.  
  227.  
  228.     mb.l = _MOUSEBUTTON(1)
  229.  
  230.     IF mb.l THEN
  231.         mx% = _MOUSEX ' Mouse column.
  232.         my% = _MOUSEY ' Mouse row%.
  233.  
  234.         IF mx% = scrb.l AND scrb.s AND my% >= scrb.t AND my% <= scrb.b OR mb.dragon THEN ' Mouse on scrollbar or doing a bar cursor drag.
  235.             SELECT CASE mb.dragon
  236.                 CASE 0
  237.                     IF my% = scrb.t AND scrb.x > 0 OR my% = scrb.b AND scrb.x + scrb.s < scrb.h THEN ' Mouse on a scrollbar arrow.
  238.                         IF my% = scrb.t THEN scrb.x = scrb.x - 1 ELSE scrb.x = scrb.x + 1 ' Top or bottom arrow.
  239.                         delay_on! = .15
  240.                         scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  241.                         scr% = scrb.i
  242.                         cursor.find = -1
  243.  
  244.                         GOSUB displayscrn: GOSUB makescrb
  245.  
  246.                     ELSEIF my% - (scrb.t + 1) >= scrb.x AND my% - (scrb.t + 1) <= scrb.x + scrb.s - 1 THEN ' Mouse on scrollbar cursor.
  247.                         mb.drag = my% - (scrb.t + 1)
  248.                         mb.dragon = -1
  249.                     ELSEIF my% > scrb.t AND my% < scrb.b OR mb.dragon THEN ' Mouse on scrollbar between scrollbar arrow and cursor.
  250.                         IF my% - (scrb.t + 1) < scrb.x THEN
  251.                             scrb.x = my% - (scrb.t + 1)
  252.                         ELSE
  253.                             scrb.x = my% - (scrb.t + 1) - (scrb.s - 1) ' The second argument compensates for large scroll cursors with fewer elements to scroll. Example: 15 elements in a 10 height scrollbar has a 3-space scrollbar cursor.
  254.                         END IF
  255.                         delay_on! = .15
  256.                         scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  257.                         scr% = scrb.i
  258.                         cursor.find = -1
  259.  
  260.                         GOSUB displayscrn: GOSUB makescrb
  261.  
  262.                     END IF
  263.  
  264.                 CASE ELSE ' Scrollbar cursor drag.
  265.                     IF my% - (scrb.t + 1) < mb.drag AND my% - (scrb.t + 1) - (mb.drag - scrb.x) >= 0 THEN
  266.                         i% = mb.drag - scrb.x
  267.                         scrb.x = my% - (scrb.t + 1) - i%
  268.                         mb.drag = scrb.x + i%
  269.                         scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  270.                         scr% = scrb.i
  271.                         cursor.find = -1
  272.  
  273.                         GOSUB displayscrn: GOSUB makescrb
  274.  
  275.                     ELSEIF my% - (scrb.t + 1) > mb.drag AND my% - (scrb.t + 1) + (scrb.x - mb.drag) < scrb.h - (scrb.s - 1) THEN
  276.                         i% = scrb.x - mb.drag
  277.                         scrb.x = my% - (scrb.t + 1) + i%
  278.                         mb.drag = scrb.x - i%
  279.                         scrb.i = INT(scrb.x * ((noe% - scrb.d) / (scrb.h - scrb.s)))
  280.                         scr% = scrb.i
  281.                         cursor.find = -1
  282.  
  283.                         GOSUB displayscrn: GOSUB makescrb
  284.                     ELSE
  285.                         i% = my% - (scrb.t + 1)
  286.                         IF i% >= scrb.t AND i% <= scrb.h THEN mb.drag = my% - (scrb.t + 1)
  287.                     END IF
  288.             END SELECT
  289.  
  290.         ELSEIF my% >= margin.t + 1 AND my% <= margin.t + page.h% THEN
  291.             IF mx% >= margin.l + 1 AND mx% <= scrn.w - margin.r THEN
  292.                 LOCATE my%, mx%, 1 ' Locate by left mouse click and show cursor.
  293.                 GOSUB getcurrow
  294.             END IF
  295.         END IF
  296.     ELSE
  297.         mb.drag = 0: mb.dragon = 0
  298.     END IF
  299.     RETURN
  300.  
  301.     getcurrow:
  302.     row% = CSRLIN - margin.t
  303.     cursor.scbrrow = row% + scr%
  304.     cursor.scbrcol = POS(0)
  305.     cursor.holdscr = scr%
  306.     cursor.holdrow = row%
  307.     cursor.holdscrbx = scrb.x
  308.     RETURN
  309.  
  310.     backtocursor:
  311.     IF cursor.scbrrow > scr% AND cursor.scbrrow <= scr% + page.h% THEN
  312.         ' Display region does not contain cursor. Do nothing.
  313.     ELSE ' Display region contains the cursor.
  314.         scr% = cursor.holdscr
  315.         row% = cursor.holdrow
  316.         scrb.x = cursor.holdscrbx
  317.         scrb.i = scr%
  318.         GOSUB makescrb
  319.         GOSUB displayscrn
  320.     END IF
  321.     RETURN
  322.  
  323.     analize:
  324.     ss% = CSRLIN: tt% = POS(0)
  325.     LOCATE 2, 1
  326.     PRINT " initiate_scrb% ="; initiate_scrb%
  327.     PRINT " scrn.w ="; scrn.w; " scrn.h ="; scrn.h; scrb.s; "     "
  328.     PRINT " margin.t ="; margin.t; " margin.b ="; margin.b; " margin.l ="; margin.l; " margin.r ="; margin.r; scrb.s; "     "
  329.     PRINT " scrb.t ="; scrb.t; " scrb.b ="; scrb.b; " scrb.l ="; scrb.l; " scrb.d ="; scrb.d; " scrb.x = "; scrb.x; " scrb.i ="; scrb.i; " scrb.h ="; scrb.h; " scrb.s ="; scrb.s; "     "
  330.     PRINT " cursor.find ="; cursor.find; " cursor.scbrrow ="; cursor.scbrrow; " cursor.scbrcol = "; cursor.scbrcol; scrb.s; "     "
  331.     PRINT " cursor.holdscr ="; cursor.holdscr; " cursor.holdrow ="; cursor.holdrow; " cursor.holdscrbx ="; cursor.holdscrbx
  332.     PRINT " page.h% ="; page.h%; " noe% = "; noe%; " delay_on! ="; delay_on!; " row% = "; row%; " scr% ="; scr%; " mx% ="; mx%; " my% ="; my%; " mb.l ="; mb.l; " mb.dragon ="; mb.dragon; " mb.drag ="; mb.drag; "     "
  333.     LOCATE ss%, tt%
  334.     _DELAY .05
  335.     RETURN
  336.  
  337.     $IF  THEN
  338.         Notes: DIM SHARED variables for a GLOBAL format option.---------------
  339.         DIM SHARED initiate_scrb%
  340.         DIM SHARED scrn.w, scrn.h
  341.         DIM SHARED margin.t, margin.b, margin.l, margin.r
  342.         DIM SHARED scrb.t, scrb.b, scrb.l, scrb.d, scrb.x, scrb.i, scrb.h, scrb.s
  343.         DIM SHARED cursor.find, cursor.scbrrow, cursor.scbrcol, cursor.holdscr, cursor.holdrow, cursor.holdscrbx
  344.         DIM SHARED page.h%, noe%, delay_on!, row%, scr%, mb.l, mb.dragon, mb.drag
  345.     $END IF
  346.  
  347.  
« Last Edit: October 29, 2020, 05:45:59 pm by Pete »
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
@Pete

I am surprised to see Types Defined in a SUB I do mine at top of module... but that doesn't seem a concern.  I would be careful to get a Type Defined before you do try to DIM a variable or array with STATIC AS the Type.

Just a couple of thoughts. That's a nice bit of code. Do you have an editor in a SUB? It looks close.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
QB64 allows TYPE in subs, but QBasic doesn't. This was a nice addition, especially for making libraries.

I have made a few editors over the years, and I'm fiddling with something new, now. I hardly ever look back at old code, because it's just fun for me to make old things new, from scratch. What I am thinking about, is my son asks me about programs from time to time, and while he isn't into learning coding from the ground up, I have no problem with him being able to put libraries together, to build some apps. As I get older, I'll probably appreciate these libraries, too. When I first started coding, I actually did libraries for games. I stopped doing that after I started business apps, simply because I only needed one app, and it would have taken a lot longer to build everything up as libraries. Funny how what is old is new again.

Again, thanks for the help in demonstrating how to use UDT's with STATIC; much appreciated.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/