QB64.org Forum

Active Forums => Programs => Topic started by: SMcNeill on January 17, 2019, 10:32:01 am

Title: Lists Linking Demo
Post by: SMcNeill on January 17, 2019, 10:32:01 am
And since STxAxTIC asked about the linkedlist.bas file which was accidently included in the zip file for the Old Dice Roller I'm working on, I thought I'd explain about it here:

Code: QB64: [Select]
  1. ''$INCLUDE:'colorall.bi'
  2. $IF KOLOR = UNDEFINED THEN
  3.     $LET KOLOR = 32
  4.  
  5. $IF KOLOR = 32 THEN
  6.     CONST AliceBlue = &HFFF0F8FF~& ' _RGB32(240,248,255)
  7.     CONST Almond = &HFFEFDECD~& '_RGB32(239,222,205)
  8.     CONST AntiqueBrass = &HFFCD9575~& '_RGB32(205,149,117)
  9.     CONST AntiqueWhite = &HFFFAEBD7~& ' _RGB32(250,235,215)
  10.     CONST Apricot = &HFFFDD9B5~& '_RGB32(253,217,181)
  11.     CONST Aqua = &HFF00FFFF~& ' _RGB32(0,255,255)
  12.     CONST Aquamarine = &HFF7FFFD4~& ' _RGB32(127,255,212)
  13.     CONST Asparagus = &HFF87A96B~& '_RGB32(135,169,107)
  14.     CONST AtomicTangerine = &HFFFFA474~& '_RGB32(255,164,116)
  15.     CONST Azure = &HFFF0FFFF~& ' _RGB32(240,255,255)
  16.     CONST BananaMania = &HFFFAE7B5~& '_RGB32(250,231,181)
  17.     CONST Beaver = &HFF9F8170~& '_RGB32(159,129,112)
  18.     CONST Beige = &HFFF5F5DC~& ' _RGB32(245,245,220)
  19.     CONST Bisque = &HFFFFE4C4~& ' _RGB32(255,228,196)
  20.     CONST Bittersweet = &HFFFD7C6E~& '_RGB32(253,124,110)
  21.     CONST Black = &HFF000000~& ' _RGB32(0,0,0)
  22.     CONST BlanchedAlmond = &HFFFFEBCD~& ' _RGB32(255,235,205)
  23.     CONST BlizzardBlue = &HFFACE5EE~& '_RGB32(172,229,238)
  24.     CONST Blue = &HFF0000FF~& ' _RGB32(0,0,255)
  25.     CONST BlueBell = &HFFA2A2D0~& '_RGB32(162,162,208)
  26.     CONST BlueGray = &HFF6699CC~& '_RGB32(102,153,204)
  27.     CONST BlueGreen = &HFF0D98BA~& '_RGB32(13,152,186)
  28.     CONST BlueViolet = &HFF8A2BE2~& ' _RGB32(138,43,226)
  29.     CONST Blush = &HFFDE5D83~& '_RGB32(222,93,131)
  30.     CONST BrickRed = &HFFCB4154~& '_RGB32(203,65,84)
  31.     CONST Brown = &HFFA52A2A~& ' _RGB32(165,42,42)
  32.     CONST BurlyWood = &HFFDEB887~& ' _RGB32(222,184,135)
  33.     CONST BurntOrange = &HFFFF7F49~& '_RGB32(255,127,73)
  34.     CONST BurntSienna = &HFFEA7E5D~& '_RGB32(234,126,93)
  35.     CONST CadetBlue = &HFF5F9EA0~& ' _RGB32(95,158,160)
  36.     CONST Canary = &HFFFFFF99~& '_RGB32(255,255,153)
  37.     CONST CaribbeanGreen = &HFF1CD3A2~& '_RGB32(28,211,162)
  38.     CONST CarnationPink = &HFFFFAACC~& '_RGB32(255,170,204)
  39.     CONST Cerise = &HFFDD4492~& '_RGB32(221,68,146)
  40.     CONST Cerulean = &HFF1DACD6~& '_RGB32(29,172,214)
  41.     CONST ChartReuse = &HFF7FFF00~& ' _RGB32(127,255,0)
  42.     CONST Chestnut = &HFFBC5D58~& '_RGB32(188,93,88)
  43.     CONST Chocolate = &HFFD2691E~& ' _RGB32(210,105,30)
  44.     CONST Copper = &HFFDD9475~& '_RGB32(221,148,117)
  45.     CONST Coral = &HFFFF7F50~& ' _RGB32(255,127,80)
  46.     CONST Cornflower = &HFF9ACEEB~& '_RGB32(154,206,235)
  47.     CONST CornflowerBlue = &HFF6495ED~& ' _RGB32(100,149,237)
  48.     CONST Cornsilk = &HFFFFF8DC~& ' _RGB32(255,248,220)
  49.     CONST CottonCandy = &HFFFFBCD9~& '_RGB32(255,188,217)
  50.     CONST CrayolaAquamarine = &HFF78DBE2~& '_RGB32(120,219,226)
  51.     CONST CrayolaBlue = &HFF1F75FE~& '_RGB32(31,117,254)
  52.     CONST CrayolaBlueViolet = &HFF7366BD~& '_RGB32(115,102,189)
  53.     CONST CrayolaBrown = &HFFB4674D~& '_RGB32(180,103,77)
  54.     CONST CrayolaCadetBlue = &HFFB0B7C6~& '_RGB32(176,183,198)
  55.     CONST CrayolaForestGreen = &HFF6DAE81~& '_RGB32(109,174,129)
  56.     CONST CrayolaGold = &HFFE7C697~& '_RGB32(231,198,151)
  57.     CONST CrayolaGoldenrod = &HFFFCD975~& '_RGB32(252,217,117)
  58.     CONST CrayolaGray = &HFF95918C~& '_RGB32(149,145,140)
  59.     CONST CrayolaGreen = &HFF1CAC78~& '_RGB32(28,172,120)
  60.     CONST CrayolaGreenYellow = &HFFF0E891~& '_RGB32(240,232,145)
  61.     CONST CrayolaIndigo = &HFF5D76CB~& '_RGB32(93,118,203)
  62.     CONST CrayolaLavender = &HFFFCB4D5~& '_RGB32(252,180,213)
  63.     CONST CrayolaMagenta = &HFFF664AF~& '_RGB32(246,100,175)
  64.     CONST CrayolaMaroon = &HFFC8385A~& '_RGB32(200,56,90)
  65.     CONST CrayolaMidnightBlue = &HFF1A4876~& '_RGB32(26,72,118)
  66.     CONST CrayolaOrange = &HFFFF7538~& '_RGB32(255,117,56)
  67.     CONST CrayolaOrangeRed = &HFFFF2B2B~& '_RGB32(255,43,43)
  68.     CONST CrayolaOrchid = &HFFE6A8D7~& '_RGB32(230,168,215)
  69.     CONST CrayolaPlum = &HFF8E4585~& '_RGB32(142,69,133)
  70.     CONST CrayolaRed = &HFFEE204D~& '_RGB32(238,32,77)
  71.     CONST CrayolaSalmon = &HFFFF9BAA~& '_RGB32(255,155,170)
  72.     CONST CrayolaSeaGreen = &HFF9FE2BF~& '_RGB32(159,226,191)
  73.     CONST CrayolaSilver = &HFFCDC5C2~& '_RGB32(205,197,194)
  74.     CONST CrayolaSkyBlue = &HFF80DAEB~& '_RGB32(128,218,235)
  75.     CONST CrayolaSpringGreen = &HFFECEABE~& '_RGB32(236,234,190)
  76.     CONST CrayolaTann = &HFFFAA76C~& '_RGB32(250,167,108)
  77.     CONST CrayolaThistle = &HFFEBC7DF~& '_RGB32(235,199,223)
  78.     CONST CrayolaViolet = &HFF926EAE~& '_RGB32(146,110,174)
  79.     CONST CrayolaYellow = &HFFFCE883~& '_RGB32(252,232,131)
  80.     CONST CrayolaYellowGreen = &HFFC5E384~& '_RGB32(197,227,132)
  81.     CONST Crimson = &HFFDC143C~& ' _RGB32(220,20,60)
  82.     CONST Cyan = &HFF00FFFF~& ' _RGB32(0,255,255)
  83.     CONST Dandelion = &HFFFDDB6D~& '_RGB32(253,219,109)
  84.     CONST DarkBlue = &HFF00008B~& ' _RGB32(0,0,139)
  85.     CONST DarkCyan = &HFF008B8B~& ' _RGB32(0,139,139)
  86.     CONST DarkGoldenRod = &HFFB8860B~& ' _RGB32(184,134,11)
  87.     CONST DarkGray = &HFFA9A9A9~& ' _RGB32(169,169,169)
  88.     CONST DarkGreen = &HFF006400~& ' _RGB32(0,100,0)
  89.     CONST DarkKhaki = &HFFBDB76B~& ' _RGB32(189,183,107)
  90.     CONST DarkMagenta = &HFF8B008B~& ' _RGB32(139,0,139)
  91.     CONST DarkOliveGreen = &HFF556B2F~& ' _RGB32(85,107,47)
  92.     CONST DarkOrange = &HFFFF8C00~& ' _RGB32(255,140,0)
  93.     CONST DarkOrchid = &HFF9932CC~& ' _RGB32(153,50,204)
  94.     CONST DarkRed = &HFF8B0000~& ' _RGB32(139,0,0)
  95.     CONST DarkSalmon = &HFFE9967A~& ' _RGB32(233,150,122)
  96.     CONST DarkSeaGreen = &HFF8FBC8F~& ' _RGB32(143,188,143)
  97.     CONST DarkSlateBlue = &HFF483D8B~& ' _RGB32(72,61,139)
  98.     CONST DarkSlateGray = &HFF2F4F4F~& ' _RGB32(47,79,79)
  99.     CONST DarkTurquoise = &HFF00CED1~& ' _RGB32(0,206,209)
  100.     CONST DarkViolet = &HFF9400D3~& ' _RGB32(148,0,211)
  101.     CONST DeepPink = &HFFFF1493~& ' _RGB32(255,20,147)
  102.     CONST DeepSkyBlue = &HFF00BFFF~& ' _RGB32(0,191,255)
  103.     CONST Denim = &HFF2B6CC4~& '_RGB32(43,108,196)
  104.     CONST DesertSand = &HFFEFCDB8~& '_RGB32(239,205,184)
  105.     CONST DimGray = &HFF696969~& ' _RGB32(105,105,105)
  106.     CONST DodgerBlue = &HFF1E90FF~& ' _RGB32(30,144,255)
  107.     CONST Eggplant = &HFF6E5160~& '_RGB32(110,81,96)
  108.     CONST ElectricLime = &HFFCEFF1D~& '_RGB32(206,255,29)
  109.     CONST Fern = &HFF71BC78~& '_RGB32(113,188,120)
  110.     CONST FireBrick = &HFFB22222~& ' _RGB32(178,34,34)
  111.     CONST Floralwhite = &HFFFFFAF0~& ' _RGB32(255,250,240)
  112.     CONST ForestGreen = &HFF228B22~& ' _RGB32(34,139,34)
  113.     CONST Fuchsia = &HFFC364C5~& '_RGB32(195,100,197)
  114.     CONST FuzzyWuzzy = &HFFCC6666~& '_RGB32(204,102,102)
  115.     CONST Gainsboro = &HFFDCDCDC~& ' _RGB32(220,220,220)
  116.     CONST GhostWhite = &HFFF8F8FF~& ' _RGB32(248,248,255)
  117.     CONST Gold = &HFFFFD700~& ' _RGB32(255,215,0)
  118.     CONST GoldenRod = &HFFDAA520~& ' _RGB32(218,165,32)
  119.     CONST GrannySmithApple = &HFFA8E4A0~& '_RGB32(168,228,160)
  120.     CONST Gray = &HFF808080~& ' _RGB32(128,128,128)
  121.     CONST Green = &HFF008000~& ' _RGB32(0,128,0)
  122.     CONST GreenBlue = &HFF1164B4~& '_RGB32(17,100,180)
  123.     CONST GreenYellow = &HFFADFF2F~& ' _RGB32(173,255,47)
  124.     CONST HoneyDew = &HFFF0FFF0~& ' _RGB32(240,255,240)
  125.     CONST HotMagenta = &HFFFF1DCE~& '_RGB32(255,29,206)
  126.     CONST HotPink = &HFFFF69B4~& ' _RGB32(255,105,180)
  127.     CONST Inchworm = &HFFB2EC5D~& '_RGB32(178,236,93)
  128.     CONST IndianRed = &HFFCD5C5C~& ' _RGB32(205,92,92)
  129.     CONST Indigo = &HFF4B0082~& ' _RGB32(75,0,130)
  130.     CONST Ivory = &HFFFFFFF0~& ' _RGB32(255,255,240)
  131.     CONST JazzberryJam = &HFFCA3767~& '_RGB32(202,55,103)
  132.     CONST JungleGreen = &HFF3BB08F~& '_RGB32(59,176,143)
  133.     CONST Khaki = &HFFF0E68C~& ' _RGB32(240,230,140)
  134.     CONST LaserLemon = &HFFFEFE22~& '_RGB32(254,254,34)
  135.     CONST Lavender = &HFFE6E6FA~& ' _RGB32(230,230,250)
  136.     CONST LavenderBlush = &HFFFFF0F5~& ' _RGB32(255,240,245)
  137.     CONST LawnGreen = &HFF7CFC00~& ' _RGB32(124,252,0)
  138.     CONST LemonChiffon = &HFFFFFACD~& ' _RGB32(255,250,205)
  139.     CONST LemonYellow = &HFFFFF44F~& '_RGB32(255,244,79)
  140.     CONST LightBlue = &HFFADD8E6~& ' _RGB32(173,216,230)
  141.     CONST LightCoral = &HFFF08080~& ' _RGB32(240,128,128)
  142.     CONST LightCyan = &HFFE0FFFF~& ' _RGB32(224,255,255)
  143.     CONST LightGoldenRodYellow = &HFFFAFAD2~& ' _RGB32(250,250,210)
  144.     CONST LightGray = &HFFD3D3D3~& ' _RGB32(211,211,211)
  145.     CONST LightGreen = &HFF90EE90~& ' _RGB32(144,238,144)
  146.     CONST LightPink = &HFFFFB6C1~& ' _RGB32(255,182,193)
  147.     CONST LightSalmon = &HFFFFA07A~& ' _RGB32(255,160,122)
  148.     CONST LightSeaGreen = &HFF20B2AA~& ' _RGB32(32,178,170)
  149.     CONST LightSkyBlue = &HFF87CEFA~& ' _RGB32(135,206,250)
  150.     CONST LightSlateGray = &HFF778899~& ' _RGB32(119,136,153)
  151.     CONST LightSteelBlue = &HFFB0C4DE~& ' _RGB32(176,196,222)
  152.     CONST LightYellow = &HFFFFFFE0~& ' _RGB32(255,255,224)
  153.     CONST Lime = &HFF00FF00~& ' _RGB32(0,255,0)
  154.     CONST LimeGreen = &HFF32CD32~& ' _RGB32(50,205,50)
  155.     CONST Linen = &HFFFAF0E6~& ' _RGB32(250,240,230)
  156.     CONST MacaroniAndCheese = &HFFFFBD88~& '_RGB32(255,189,136)
  157.     CONST Magenta = &HFFFF00FF~& ' _RGB32(255,0,255)
  158.     CONST MagicMint = &HFFAAF0D1~& '_RGB32(170,240,209)
  159.     CONST Mahogany = &HFFCD4A4C~& '_RGB32(205,74,76)
  160.     CONST Maize = &HFFEDD19C~& '_RGB32(237,209,156)
  161.     CONST Manatee = &HFF979AAA~& '_RGB32(151,154,170)
  162.     CONST MangoTango = &HFFFF8243~& '_RGB32(255,130,67)
  163.     CONST Maroon = &HFF800000~& ' _RGB32(128,0,0)
  164.     CONST Mauvelous = &HFFEF98AA~& '_RGB32(239,152,170)
  165.     CONST MediumAquamarine = &HFF66CDAA~& ' _RGB32(102,205,170)
  166.     CONST MediumBlue = &HFF0000CD~& ' _RGB32(0,0,205)
  167.     CONST MediumOrchid = &HFFBA55D3~& ' _RGB32(186,85,211)
  168.     CONST MediumPurple = &HFF9370DB~& ' _RGB32(147,112,219)
  169.     CONST MediumSeaGreen = &HFF3CB371~& ' _RGB32(60,179,113)
  170.     CONST MediumSlateBlue = &HFF7B68EE~& ' _RGB32(123,104,238)
  171.     CONST MediumSpringGreen = &HFF00FA9A~& ' _RGB32(0,250,154)
  172.     CONST MediumTurquoise = &HFF48D1CC~& ' _RGB32(72,209,204)
  173.     CONST MediumVioletRed = &HFFC71585~& ' _RGB32(199,21,133)
  174.     CONST Melon = &HFFFDBCB4~& '_RGB32(253,188,180)
  175.     CONST MidnightBlue = &HFF191970~& ' _RGB32(25,25,112)
  176.     CONST MintCream = &HFFF5FFFA~& ' _RGB32(245,255,250)
  177.     CONST MistyRose = &HFFFFE4E1~& ' _RGB32(255,228,225)
  178.     CONST Moccasin = &HFFFFE4B5~& ' _RGB32(255,228,181)
  179.     CONST MountainMeadow = &HFF30BA8F~& '_RGB32(48,186,143)
  180.     CONST Mulberry = &HFFC54B8C~& '_RGB32(197,75,140)
  181.     CONST NavajoWhite = &HFFFFDEAD~& ' _RGB32(255,222,173)
  182.     CONST Navy = &HFF000080~& ' _RGB32(0,0,128)
  183.     CONST NavyBlue = &HFF1974D2~& '_RGB32(25,116,210)
  184.     CONST NeonCarrot = &HFFFFA343~& '_RGB32(255,163,67)
  185.     CONST OldLace = &HFFFDF5E6~& ' _RGB32(253,245,230)
  186.     CONST Olive = &HFF808000~& ' _RGB32(128,128,0)
  187.     CONST OliveDrab = &HFF6B8E23~& ' _RGB32(107,142,35)
  188.     CONST OliveGreen = &HFFBAB86C~& '_RGB32(186,184,108)
  189.     CONST Orange = &HFFFFA500~& ' _RGB32(255,165,0)
  190.     CONST OrangeRed = &HFFFF4500~& ' _RGB32(255,69,0)
  191.     CONST OrangeYellow = &HFFF8D568~& '_RGB32(248,213,104)
  192.     CONST Orchid = &HFFDA70D6~& ' _RGB32(218,112,214)
  193.     CONST OuterSpace = &HFF414A4C~& '_RGB32(65,74,76)
  194.     CONST OutrageousOrange = &HFFFF6E4A~& '_RGB32(255,110,74)
  195.     CONST PacificBlue = &HFF1CA9C9~& '_RGB32(28,169,201)
  196.     CONST PaleGoldenRod = &HFFEEE8AA~& ' _RGB32(238,232,170)
  197.     CONST PaleGreen = &HFF98FB98~& ' _RGB32(152,251,152)
  198.     CONST PaleTurquoise = &HFFAFEEEE~& ' _RGB32(175,238,238)
  199.     CONST PaleVioletRed = &HFFDB7093~& ' _RGB32(219,112,147)
  200.     CONST PapayaWhip = &HFFFFEFD5~& ' _RGB32(255,239,213)
  201.     CONST Peach = &HFFFFCFAB~& '_RGB32(255,207,171)
  202.     CONST PeachPuff = &HFFFFDAB9~& ' _RGB32(255,218,185)
  203.     CONST Periwinkle = &HFFC5D0E6~& '_RGB32(197,208,230)
  204.     CONST Peru = &HFFCD853F~& ' _RGB32(205,133,63)
  205.     CONST PiggyPink = &HFFFDDDE6~& '_RGB32(253,221,230)
  206.     CONST PineGreen = &HFF158078~& '_RGB32(21,128,120)
  207.     CONST Pink = &HFFFFC0CB~& ' _RGB32(255,192,203)
  208.     CONST PinkFlamingo = &HFFFC74FD~& '_RGB32(252,116,253)
  209.     CONST PinkSherbet = &HFFF78FA7~& '_RGB32(247,143,167)
  210.     CONST Plum = &HFFDDA0DD~& ' _RGB32(221,160,221)
  211.     CONST PowderBlue = &HFFB0E0E6~& ' _RGB32(176,224,230)
  212.     CONST Purple = &HFF800080~& ' _RGB32(128,0,128)
  213.     CONST PurpleHeart = &HFF7442C8~& '_RGB32(116,66,200)
  214.     CONST PurpleMountainsMajesty = &HFF9D81BA~& '_RGB32(157,129,186)
  215.     CONST PurplePizzazz = &HFFFE4EDA~& '_RGB32(254,78,218)
  216.     CONST RadicalRed = &HFFFF496C~& '_RGB32(255,73,108)
  217.     CONST RawSienna = &HFFD68A59~& '_RGB32(214,138,89)
  218.     CONST RawUmber = &HFF714B23~& '_RGB32(113,75,35)
  219.     CONST RazzleDazzleRose = &HFFFF48D0~& '_RGB32(255,72,208)
  220.     CONST Razzmatazz = &HFFE3256B~& '_RGB32(227,37,107)
  221.     CONST Red = &HFFFF0000~& ' _RGB32(255,0,0)
  222.     CONST RedOrange = &HFFFF5349~& '_RGB32(255,83,73)
  223.     CONST RedViolet = &HFFC0448F~& '_RGB32(192,68,143)
  224.     CONST RobinsEggBlue = &HFF1FCECB~& '_RGB32(31,206,203)
  225.     CONST RosyBrown = &HFFBC8F8F~& ' _RGB32(188,143,143)
  226.     CONST RoyalBlue = &HFF4169E1~& ' _RGB32(65,105,225)
  227.     CONST RoyalPurple = &HFF7851A9~& '_RGB32(120,81,169)
  228.     CONST SaddleBrown = &HFF8B4513~& ' _RGB32(139,69,19)
  229.     CONST Salmon = &HFFFA8072~& ' _RGB32(250,128,114)
  230.     CONST SandyBrown = &HFFF4A460~& ' _RGB32(244,164,96)
  231.     CONST Scarlet = &HFFFC2847~& '_RGB32(252,40,71)
  232.     CONST ScreaminGreen = &HFF76FF7A~& '_RGB32(118,255,122)
  233.     CONST SeaGreen = &HFF2E8B57~& ' _RGB32(46,139,87)
  234.     CONST SeaShell = &HFFFFF5EE~& ' _RGB32(255,245,238)
  235.     CONST Sepia = &HFFA5694F~& '_RGB32(165,105,79)
  236.     CONST Shadow = &HFF8A795D~& '_RGB32(138,121,93)
  237.     CONST Shamrock = &HFF45CEA2~& '_RGB32(69,206,162)
  238.     CONST ShockingPink = &HFFFB7EFD~& '_RGB32(251,126,253)
  239.     CONST Sienna = &HFFA0522D~& ' _RGB32(160,82,45)
  240.     CONST Silver = &HFFC0C0C0~& ' _RGB32(192,192,192)
  241.     CONST SkyBlue = &HFF87CEEB~& ' _RGB32(135,206,235)
  242.     CONST SlateBlue = &HFF6A5ACD~& ' _RGB32(106,90,205)
  243.     CONST SlateGray = &HFF708090~& ' _RGB32(112,128,144)
  244.     CONST Snow = &HFFFFFAFA~& ' _RGB32(255,250,250)
  245.     CONST SpringGreen = &HFF00FF7F~& ' _RGB32(0,255,127)
  246.     CONST SteelBlue = &HFF4682B4~& ' _RGB32(70,130,180)
  247.     CONST Sunglow = &HFFFFCF48~& '_RGB32(255,207,72)
  248.     CONST SunsetOrange = &HFFFD5E53~& '_RGB32(253,94,83)
  249.     CONST Tann = &HFFD2B48C~& ' _RGB32(210,180,140)
  250.     CONST Teal = &HFF008080~& ' _RGB32(0,128,128)
  251.     CONST TealBlue = &HFF18A7B5~& '_RGB32(24,167,181)
  252.     CONST Thistle = &HFFD8BFD8~& ' _RGB32(216,191,216)
  253.     CONST TickleMePink = &HFFFC89AC~& '_RGB32(252,137,172)
  254.     CONST Timberwolf = &HFFDBD7D2~& '_RGB32(219,215,210)
  255.     CONST Tomato = &HFFFF6347~& ' _RGB32(255,99,71)
  256.     CONST TropicalRainForest = &HFF17806D~& '_RGB32(23,128,109)
  257.     CONST Tumbleweed = &HFFDEAA88~& '_RGB32(222,170,136)
  258.     CONST Turquoise = &HFF40E0D0~& ' _RGB32(64,224,208)
  259.     CONST TurquoiseBlue = &HFF77DDE7~& '_RGB32(119,221,231)
  260.     CONST UnmellowYellow = &HFFFFFF66~& '_RGB32(255,255,102)
  261.     CONST Violet = &HFFEE82EE~& ' _RGB32(238,130,238)
  262.     CONST VioletBlue = &HFF324AB2~& '_RGB32(50,74,178)
  263.     CONST VioletRed = &HFFF75394~& '_RGB32(247,83,148)
  264.     CONST VividTangerine = &HFFFFA089~& '_RGB32(255,160,137)
  265.     CONST VividViolet = &HFF8F509D~& '_RGB32(143,80,157)
  266.     CONST Wheat = &HFFF5DEB3~& ' _RGB32(245,222,179)
  267.     CONST White = &HFFFFFFFF~& ' _RGB32(255,255,255)
  268.     CONST Whitesmoke = &HFFF5F5F5~& ' _RGB32(245,245,245)
  269.     CONST WildBlueYonder = &HFFA2ADD0~& '_RGB32(162,173,208)
  270.     CONST WildStrawberry = &HFFFF43A4~& '_RGB32(255,67,164)
  271.     CONST WildWatermelon = &HFFFC6C85~& '_RGB32(252,108,133)
  272.     CONST Wisteria = &HFFCDA4DE~& '_RGB32(205,164,222)
  273.     CONST Yellow = &HFFFFFF00~& ' _RGB32(255,255,0)
  274.     CONST YellowGreen = &HFF9ACD32~& ' _RGB32(154,205,50)
  275.     CONST YellowOrange = &HFFFFAE42~& '_RGB32(255,174,66)
  276.  
  277. $IF KOLOR = 0 THEN
  278.     CONST Black = 0~%%
  279.     CONST Blue = 1~%%
  280.     CONST Green = 2~%%
  281.     CONST Cyan = 3~%%
  282.     CONST Red = 4~%%
  283.     CONST Magenta = 5~%%
  284.     CONST Brown = 6~%%
  285.     CONST White = 7~%%
  286.     CONST Gray = 8~%%
  287.     CONST LightBlue = 9~%%
  288.     CONST LightGreen = 10~%%
  289.     CONST LightCyan = 11~%%
  290.     CONST LightRed = 12~%%
  291.     CONST LightMagenta = 13~%%
  292.     CONST Yellow = 14~%%
  293.     CONST BrightWhite = 15~%%
  294.     CONST Blink = 16~%%
  295.  
  296. $IF KOLOR = 256 THEN
  297.     CONST Black = 0~%%
  298.     CONST Blue = 1~%%
  299.     CONST Green = 2~%%
  300.     CONST Cyan = 3~%%
  301.     CONST Red = 4~%%
  302.     CONST Magenta = 5~%%
  303.     CONST Brown = 6~%%
  304.     CONST White = 7~%%
  305.     CONST Gray = 8~%%
  306.     CONST LightBlue = 9~%%
  307.     CONST LightGreen = 10~%%
  308.     CONST LightCyan = 11~%%
  309.     CONST LightRed = 12~%%
  310.     CONST LightMagenta = 13~%%
  311.     CONST Yellow = 14~%%
  312.     CONST BrightWhite = 15~%%
  313.     _PALETTECOLOR 16, _RGBA32(240, 248, 255, 255): CONST AliceBlue = 16~%%
  314.     _PALETTECOLOR 17, _RGBA32(239, 222, 205, 255): CONST Almond = 17~%%
  315.     _PALETTECOLOR 18, _RGBA32(205, 149, 117, 255): CONST AntiqueBrass = 18~%%
  316.     _PALETTECOLOR 19, _RGBA32(250, 235, 215, 255): CONST AntiqueWhite = 19~%%
  317.     _PALETTECOLOR 20, _RGBA32(253, 217, 181, 255): CONST Apricot = 20~%%
  318.     _PALETTECOLOR 21, _RGBA32(0, 255, 255, 255): CONST Aqua = 21~%%
  319.     _PALETTECOLOR 22, _RGBA32(127, 255, 212, 255): CONST Aquamarine = 22~%%
  320.     _PALETTECOLOR 23, _RGBA32(135, 169, 107, 255): CONST Asparagus = 23~%%
  321.     _PALETTECOLOR 24, _RGBA32(255, 164, 116, 255): CONST AtomicTangerine = 24~%%
  322.     _PALETTECOLOR 25, _RGBA32(240, 255, 255, 255): CONST Azure = 25~%%
  323.     _PALETTECOLOR 26, _RGBA32(250, 231, 181, 255): CONST BananaMania = 26~%%
  324.     _PALETTECOLOR 27, _RGBA32(159, 129, 112, 255): CONST Beaver = 27~%%
  325.     _PALETTECOLOR 28, _RGBA32(245, 245, 220, 255): CONST Beige = 28~%%
  326.     _PALETTECOLOR 29, _RGBA32(255, 228, 196, 255): CONST Bisque = 29~%%
  327.     _PALETTECOLOR 30, _RGBA32(253, 124, 110, 255): CONST Bittersweet = 30~%%
  328.     _PALETTECOLOR 31, _RGBA32(255, 235, 205, 255): CONST BlanchedAlmond = 31~%%
  329.     _PALETTECOLOR 32, _RGBA32(172, 229, 238, 255): CONST BlizzardBlue = 32~%%
  330.     _PALETTECOLOR 33, _RGBA32(162, 162, 208, 255): CONST BlueBell = 33~%%
  331.     _PALETTECOLOR 34, _RGBA32(102, 153, 204, 255): CONST BlueGray = 34~%%
  332.     _PALETTECOLOR 35, _RGBA32(13, 152, 186, 255): CONST BlueGreen = 35~%%
  333.     _PALETTECOLOR 36, _RGBA32(138, 43, 226, 255): CONST BlueViolet = 36~%%
  334.     _PALETTECOLOR 37, _RGBA32(222, 93, 131, 255): CONST Blush = 37~%%
  335.     _PALETTECOLOR 38, _RGBA32(203, 65, 84, 255): CONST BrickRed = 38~%%
  336.     _PALETTECOLOR 39, _RGBA32(222, 184, 135, 255): CONST BurlyWood = 39~%%
  337.     _PALETTECOLOR 40, _RGBA32(255, 127, 73, 255): CONST BurntOrange = 40~%%
  338.     _PALETTECOLOR 41, _RGBA32(234, 126, 93, 255): CONST BurntSienna = 41~%%
  339.     _PALETTECOLOR 42, _RGBA32(95, 158, 160, 255): CONST CadetBlue = 42~%%
  340.     _PALETTECOLOR 43, _RGBA32(255, 255, 153, 255): CONST Canary = 43~%%
  341.     _PALETTECOLOR 44, _RGBA32(28, 211, 162, 255): CONST CaribbeanGreen = 44~%%
  342.     _PALETTECOLOR 45, _RGBA32(255, 170, 204, 255): CONST CarnationPink = 45~%%
  343.     _PALETTECOLOR 46, _RGBA32(221, 68, 146, 255): CONST Cerise = 46~%%
  344.     _PALETTECOLOR 47, _RGBA32(29, 172, 214, 255): CONST Cerulean = 47~%%
  345.     _PALETTECOLOR 48, _RGBA32(127, 255, 0, 255): CONST ChartReuse = 48~%%
  346.     _PALETTECOLOR 49, _RGBA32(188, 93, 88, 255): CONST Chestnut = 49~%%
  347.     _PALETTECOLOR 50, _RGBA32(210, 105, 30, 255): CONST Chocolate = 50~%%
  348.     _PALETTECOLOR 51, _RGBA32(221, 148, 117, 255): CONST Copper = 51~%%
  349.     _PALETTECOLOR 52, _RGBA32(255, 127, 80, 255): CONST Coral = 52~%%
  350.     _PALETTECOLOR 53, _RGBA32(154, 206, 235, 255): CONST Cornflower = 53~%%
  351.     _PALETTECOLOR 54, _RGBA32(100, 149, 237, 255): CONST CornflowerBlue = 54~%%
  352.     _PALETTECOLOR 55, _RGBA32(255, 248, 220, 255): CONST Cornsilk = 55~%%
  353.     _PALETTECOLOR 56, _RGBA32(255, 188, 217, 255): CONST CottonCandy = 56~%%
  354.     _PALETTECOLOR 57, _RGBA32(220, 20, 60, 255): CONST Crimson = 57~%%
  355.     _PALETTECOLOR 58, _RGBA32(253, 219, 109, 255): CONST Dandelion = 58~%%
  356.     _PALETTECOLOR 59, _RGBA32(0, 0, 139, 255): CONST DarkBlue = 59~%%
  357.     _PALETTECOLOR 60, _RGBA32(0, 139, 139, 255): CONST DarkCyan = 60~%%
  358.     _PALETTECOLOR 61, _RGBA32(184, 134, 11, 255): CONST DarkGoldenRod = 61~%%
  359.     _PALETTECOLOR 62, _RGBA32(169, 169, 169, 255): CONST DarkGray = 62~%%
  360.     _PALETTECOLOR 63, _RGBA32(0, 100, 0, 255): CONST DarkGreen = 63~%%
  361.     _PALETTECOLOR 64, _RGBA32(189, 183, 107, 255): CONST DarkKhaki = 64~%%
  362.     _PALETTECOLOR 65, _RGBA32(139, 0, 139, 255): CONST DarkMagenta = 65~%%
  363.     _PALETTECOLOR 66, _RGBA32(85, 107, 47, 255): CONST DarkOliveGreen = 66~%%
  364.     _PALETTECOLOR 67, _RGBA32(255, 140, 0, 255): CONST DarkOrange = 67~%%
  365.     _PALETTECOLOR 68, _RGBA32(153, 50, 204, 255): CONST DarkOrchid = 68~%%
  366.     _PALETTECOLOR 69, _RGBA32(139, 0, 0, 255): CONST DarkRed = 69~%%
  367.     _PALETTECOLOR 70, _RGBA32(233, 150, 122, 255): CONST DarkSalmon = 70~%%
  368.     _PALETTECOLOR 71, _RGBA32(143, 188, 143, 255): CONST DarkSeaGreen = 71~%%
  369.     _PALETTECOLOR 72, _RGBA32(72, 61, 139, 255): CONST DarkSlateBlue = 72~%%
  370.     _PALETTECOLOR 73, _RGBA32(47, 79, 79, 255): CONST DarkSlateGray = 73~%%
  371.     _PALETTECOLOR 74, _RGBA32(0, 206, 209, 255): CONST DarkTurquoise = 74~%%
  372.     _PALETTECOLOR 75, _RGBA32(148, 0, 211, 255): CONST DarkViolet = 75~%%
  373.     _PALETTECOLOR 76, _RGBA32(255, 20, 147, 255): CONST DeepPink = 76~%%
  374.     _PALETTECOLOR 77, _RGBA32(0, 191, 255, 255): CONST DeepSkyBlue = 77~%%
  375.     _PALETTECOLOR 78, _RGBA32(43, 108, 196, 255): CONST Denim = 78~%%
  376.     _PALETTECOLOR 79, _RGBA32(239, 205, 184, 255): CONST DesertSand = 79~%%
  377.     _PALETTECOLOR 80, _RGBA32(105, 105, 105, 255): CONST DimGray = 80~%%
  378.     _PALETTECOLOR 81, _RGBA32(30, 144, 255, 255): CONST DodgerBlue = 81~%%
  379.     _PALETTECOLOR 82, _RGBA32(110, 81, 96, 255): CONST Eggplant = 82~%%
  380.     _PALETTECOLOR 83, _RGBA32(206, 255, 29, 255): CONST ElectricLime = 83~%%
  381.     _PALETTECOLOR 84, _RGBA32(113, 188, 120, 255): CONST Fern = 84~%%
  382.     _PALETTECOLOR 85, _RGBA32(178, 34, 34, 255): CONST FireBrick = 85~%%
  383.     _PALETTECOLOR 86, _RGBA32(255, 250, 240, 255): CONST Floralwhite = 86~%%
  384.     _PALETTECOLOR 87, _RGBA32(34, 139, 34, 255): CONST ForestGreen = 87~%%
  385.     _PALETTECOLOR 88, _RGBA32(195, 100, 197, 255): CONST Fuchsia = 88~%%
  386.     _PALETTECOLOR 89, _RGBA32(204, 102, 102, 255): CONST FuzzyWuzzy = 89~%%
  387.     _PALETTECOLOR 90, _RGBA32(220, 220, 220, 255): CONST Gainsboro = 90~%%
  388.     _PALETTECOLOR 91, _RGBA32(248, 248, 255, 255): CONST GhostWhite = 91~%%
  389.     _PALETTECOLOR 92, _RGBA32(255, 215, 0, 255): CONST Gold = 92~%%
  390.     _PALETTECOLOR 93, _RGBA32(218, 165, 32, 255): CONST GoldenRod = 93~%%
  391.     _PALETTECOLOR 94, _RGBA32(168, 228, 160, 255): CONST GrannySmithApple = 94~%%
  392.     _PALETTECOLOR 95, _RGBA32(17, 100, 180, 255): CONST GreenBlue = 95~%%
  393.     _PALETTECOLOR 96, _RGBA32(173, 255, 47, 255): CONST GreenYellow = 96~%%
  394.     _PALETTECOLOR 97, _RGBA32(240, 255, 240, 255): CONST HoneyDew = 97~%%
  395.     _PALETTECOLOR 98, _RGBA32(255, 29, 206, 255): CONST HotMagenta = 98~%%
  396.     _PALETTECOLOR 99, _RGBA32(255, 105, 180, 255): CONST HotPink = 99~%%
  397.     _PALETTECOLOR 100, _RGBA32(178, 236, 93, 255): CONST Inchworm = 100~%%
  398.     _PALETTECOLOR 101, _RGBA32(205, 92, 92, 255): CONST IndianRed = 101~%%
  399.     _PALETTECOLOR 102, _RGBA32(75, 0, 130, 255): CONST Indigo = 102~%%
  400.     _PALETTECOLOR 103, _RGBA32(255, 255, 240, 255): CONST Ivory = 103~%%
  401.     _PALETTECOLOR 104, _RGBA32(202, 55, 103, 255): CONST JazzberryJam = 104~%%
  402.     _PALETTECOLOR 105, _RGBA32(59, 176, 143, 255): CONST JungleGreen = 105~%%
  403.     _PALETTECOLOR 106, _RGBA32(240, 230, 140, 255): CONST Khaki = 106~%%
  404.     _PALETTECOLOR 107, _RGBA32(254, 254, 34, 255): CONST LaserLemon = 107~%%
  405.     _PALETTECOLOR 108, _RGBA32(230, 230, 250, 255): CONST Lavender = 108~%%
  406.     _PALETTECOLOR 109, _RGBA32(255, 240, 245, 255): CONST LavenderBlush = 109~%%
  407.     _PALETTECOLOR 110, _RGBA32(124, 252, 0, 255): CONST LawnGreen = 110~%%
  408.     _PALETTECOLOR 111, _RGBA32(255, 250, 205, 255): CONST LemonChiffon = 111~%%
  409.     _PALETTECOLOR 112, _RGBA32(255, 244, 79, 255): CONST LemonYellow = 112~%%
  410.     _PALETTECOLOR 113, _RGBA32(240, 128, 128, 255): CONST LightCoral = 113~%%
  411.     _PALETTECOLOR 114, _RGBA32(250, 250, 210, 255): CONST LightGoldenRodYellow = 114~%%
  412.     _PALETTECOLOR 115, _RGBA32(211, 211, 211, 255): CONST LightGray = 115~%%
  413.     _PALETTECOLOR 116, _RGBA32(144, 238, 144, 255): CONST LightGreen2 = 116~%%
  414.     _PALETTECOLOR 117, _RGBA32(255, 182, 193, 255): CONST LightPink = 117~%%
  415.     _PALETTECOLOR 118, _RGBA32(255, 160, 122, 255): CONST LightSalmon = 118~%%
  416.     _PALETTECOLOR 119, _RGBA32(32, 178, 170, 255): CONST LightSeaGreen = 119~%%
  417.     _PALETTECOLOR 120, _RGBA32(135, 206, 250, 255): CONST LightSkyBlue = 120~%%
  418.     _PALETTECOLOR 121, _RGBA32(119, 136, 153, 255): CONST LightSlateGray = 121~%%
  419.     _PALETTECOLOR 122, _RGBA32(176, 196, 222, 255): CONST LightSteelBlue = 122~%%
  420.     _PALETTECOLOR 123, _RGBA32(255, 255, 224, 255): CONST LightYellow = 123~%%
  421.     _PALETTECOLOR 124, _RGBA32(0, 255, 0, 255): CONST Lime = 124~%%
  422.     _PALETTECOLOR 125, _RGBA32(50, 205, 50, 255): CONST LimeGreen = 125~%%
  423.     _PALETTECOLOR 126, _RGBA32(250, 240, 230, 255): CONST Linen = 126~%%
  424.     _PALETTECOLOR 127, _RGBA32(255, 189, 136, 255): CONST MacaroniAndCheese = 127~%%
  425.     _PALETTECOLOR 128, _RGBA32(170, 240, 209, 255): CONST MagicMint = 128~%%
  426.     _PALETTECOLOR 129, _RGBA32(205, 74, 76, 255): CONST Mahogany = 129~%%
  427.     _PALETTECOLOR 130, _RGBA32(237, 209, 156, 255): CONST Maize = 130~%%
  428.     _PALETTECOLOR 131, _RGBA32(151, 154, 170, 255): CONST Manatee = 131~%%
  429.     _PALETTECOLOR 132, _RGBA32(255, 130, 67, 255): CONST MangoTango = 132~%%
  430.     _PALETTECOLOR 133, _RGBA32(128, 0, 0, 255): CONST Maroon = 133~%%
  431.     _PALETTECOLOR 134, _RGBA32(239, 152, 170, 255): CONST Mauvelous = 134~%%
  432.     _PALETTECOLOR 135, _RGBA32(102, 205, 170, 255): CONST MediumAquamarine = 135~%%
  433.     _PALETTECOLOR 136, _RGBA32(0, 0, 205, 255): CONST MediumBlue = 136~%%
  434.     _PALETTECOLOR 137, _RGBA32(186, 85, 211, 255): CONST MediumOrchid = 137~%%
  435.     _PALETTECOLOR 138, _RGBA32(147, 112, 219, 255): CONST MediumPurple = 138~%%
  436.     _PALETTECOLOR 139, _RGBA32(60, 179, 113, 255): CONST MediumSeaGreen = 139~%%
  437.     _PALETTECOLOR 140, _RGBA32(123, 104, 238, 255): CONST MediumSlateBlue = 140~%%
  438.     _PALETTECOLOR 141, _RGBA32(0, 250, 154, 255): CONST MediumSpringGreen = 141~%%
  439.     _PALETTECOLOR 142, _RGBA32(72, 209, 204, 255): CONST MediumTurquoise = 142~%%
  440.     _PALETTECOLOR 143, _RGBA32(199, 21, 133, 255): CONST MediumVioletRed = 143~%%
  441.     _PALETTECOLOR 144, _RGBA32(253, 188, 180, 255): CONST Melon = 144~%%
  442.     _PALETTECOLOR 145, _RGBA32(25, 25, 112, 255): CONST MidnightBlue = 145~%%
  443.     _PALETTECOLOR 146, _RGBA32(245, 255, 250, 255): CONST MintCream = 146~%%
  444.     _PALETTECOLOR 147, _RGBA32(255, 228, 225, 255): CONST MistyRose = 147~%%
  445.     _PALETTECOLOR 148, _RGBA32(255, 228, 181, 255): CONST Moccasin = 148~%%
  446.     _PALETTECOLOR 149, _RGBA32(48, 186, 143, 255): CONST MountainMeadow = 149~%%
  447.     _PALETTECOLOR 150, _RGBA32(197, 75, 140, 255): CONST Mulberry = 150~%%
  448.     _PALETTECOLOR 151, _RGBA32(255, 222, 173, 255): CONST NavajoWhite = 151~%%
  449.     _PALETTECOLOR 152, _RGBA32(0, 0, 128, 255): CONST Navy = 152~%%
  450.     _PALETTECOLOR 153, _RGBA32(25, 116, 210, 255): CONST NavyBlue = 153~%%
  451.     _PALETTECOLOR 154, _RGBA32(255, 163, 67, 255): CONST NeonCarrot = 154~%%
  452.     _PALETTECOLOR 155, _RGBA32(253, 245, 230, 255): CONST OldLace = 155~%%
  453.     _PALETTECOLOR 156, _RGBA32(128, 128, 0, 255): CONST Olive = 156~%%
  454.     _PALETTECOLOR 157, _RGBA32(107, 142, 35, 255): CONST OliveDrab = 157~%%
  455.     _PALETTECOLOR 158, _RGBA32(186, 184, 108, 255): CONST OliveGreen = 158~%%
  456.     _PALETTECOLOR 159, _RGBA32(255, 165, 0, 255): CONST Orange = 159~%%
  457.     _PALETTECOLOR 160, _RGBA32(255, 69, 0, 255): CONST OrangeRed = 160~%%
  458.     _PALETTECOLOR 161, _RGBA32(248, 213, 104, 255): CONST OrangeYellow = 161~%%
  459.     _PALETTECOLOR 162, _RGBA32(218, 112, 214, 255): CONST Orchid = 162~%%
  460.     _PALETTECOLOR 163, _RGBA32(65, 74, 76, 255): CONST OuterSpace = 163~%%
  461.     _PALETTECOLOR 164, _RGBA32(255, 110, 74, 255): CONST OutrageousOrange = 164~%%
  462.     _PALETTECOLOR 165, _RGBA32(28, 169, 201, 255): CONST PacificBlue = 165~%%
  463.     _PALETTECOLOR 166, _RGBA32(238, 232, 170, 255): CONST PaleGoldenRod = 166~%%
  464.     _PALETTECOLOR 167, _RGBA32(152, 251, 152, 255): CONST PaleGreen = 167~%%
  465.     _PALETTECOLOR 168, _RGBA32(175, 238, 238, 255): CONST PaleTurquoise = 168~%%
  466.     _PALETTECOLOR 169, _RGBA32(219, 112, 147, 255): CONST PaleVioletRed = 169~%%
  467.     _PALETTECOLOR 170, _RGBA32(255, 239, 213, 255): CONST PapayaWhip = 170~%%
  468.     _PALETTECOLOR 171, _RGBA32(255, 207, 171, 255): CONST Peach = 171~%%
  469.     _PALETTECOLOR 172, _RGBA32(255, 218, 185, 255): CONST PeachPuff = 172~%%
  470.     _PALETTECOLOR 173, _RGBA32(197, 208, 230, 255): CONST Periwinkle = 173~%%
  471.     _PALETTECOLOR 174, _RGBA32(205, 133, 63, 255): CONST Peru = 174~%%
  472.     _PALETTECOLOR 175, _RGBA32(253, 221, 230, 255): CONST PiggyPink = 175~%%
  473.     _PALETTECOLOR 176, _RGBA32(21, 128, 120, 255): CONST PineGreen = 176~%%
  474.     _PALETTECOLOR 177, _RGBA32(255, 192, 203, 255): CONST Pink = 177~%%
  475.     _PALETTECOLOR 178, _RGBA32(252, 116, 253, 255): CONST PinkFlamingo = 178~%%
  476.     _PALETTECOLOR 179, _RGBA32(247, 143, 167, 255): CONST PinkSherbet = 179~%%
  477.     _PALETTECOLOR 180, _RGBA32(221, 160, 221, 255): CONST Plum = 180~%%
  478.     _PALETTECOLOR 181, _RGBA32(176, 224, 230, 255): CONST PowderBlue = 181~%%
  479.     _PALETTECOLOR 182, _RGBA32(128, 0, 128, 255): CONST Purple = 182~%%
  480.     _PALETTECOLOR 183, _RGBA32(116, 66, 200, 255): CONST PurpleHeart = 183~%%
  481.     _PALETTECOLOR 184, _RGBA32(157, 129, 186, 255): CONST PurpleMountainsMajesty = 184~%%
  482.     _PALETTECOLOR 185, _RGBA32(254, 78, 218, 255): CONST PurplePizzazz = 185~%%
  483.     _PALETTECOLOR 186, _RGBA32(255, 73, 108, 255): CONST RadicalRed = 186~%%
  484.     _PALETTECOLOR 187, _RGBA32(214, 138, 89, 255): CONST RawSienna = 187~%%
  485.     _PALETTECOLOR 188, _RGBA32(113, 75, 35, 255): CONST RawUmber = 188~%%
  486.     _PALETTECOLOR 189, _RGBA32(255, 72, 208, 255): CONST RazzleDazzleRose = 189~%%
  487.     _PALETTECOLOR 190, _RGBA32(227, 37, 107, 255): CONST Razzmatazz = 190~%%
  488.     _PALETTECOLOR 191, _RGBA32(255, 83, 73, 255): CONST RedOrange = 191~%%
  489.     _PALETTECOLOR 192, _RGBA32(192, 68, 143, 255): CONST RedViolet = 192~%%
  490.     _PALETTECOLOR 193, _RGBA32(31, 206, 203, 255): CONST RobinsEggBlue = 193~%%
  491.     _PALETTECOLOR 194, _RGBA32(188, 143, 143, 255): CONST RosyBrown = 194~%%
  492.     _PALETTECOLOR 195, _RGBA32(65, 105, 225, 255): CONST RoyalBlue = 195~%%
  493.     _PALETTECOLOR 196, _RGBA32(120, 81, 169, 255): CONST RoyalPurple = 196~%%
  494.     _PALETTECOLOR 197, _RGBA32(139, 69, 19, 255): CONST SaddleBrown = 197~%%
  495.     _PALETTECOLOR 198, _RGBA32(250, 128, 114, 255): CONST Salmon = 198~%%
  496.     _PALETTECOLOR 199, _RGBA32(244, 164, 96, 255): CONST SandyBrown = 199~%%
  497.     _PALETTECOLOR 200, _RGBA32(252, 40, 71, 255): CONST Scarlet = 200~%%
  498.     _PALETTECOLOR 201, _RGBA32(118, 255, 122, 255): CONST ScreaminGreen = 201~%%
  499.     _PALETTECOLOR 202, _RGBA32(46, 139, 87, 255): CONST SeaGreen = 202~%%
  500.     _PALETTECOLOR 203, _RGBA32(255, 245, 238, 255): CONST SeaShell = 203~%%
  501.     _PALETTECOLOR 204, _RGBA32(165, 105, 79, 255): CONST Sepia = 204~%%
  502.     _PALETTECOLOR 205, _RGBA32(138, 121, 93, 255): CONST Shadow = 205~%%
  503.     _PALETTECOLOR 206, _RGBA32(69, 206, 162, 255): CONST Shamrock = 206~%%
  504.     _PALETTECOLOR 207, _RGBA32(251, 126, 253, 255): CONST ShockingPink = 207~%%
  505.     _PALETTECOLOR 208, _RGBA32(160, 82, 45, 255): CONST Sienna = 208~%%
  506.     _PALETTECOLOR 209, _RGBA32(192, 192, 192, 255): CONST Silver = 209~%%
  507.     _PALETTECOLOR 210, _RGBA32(135, 206, 235, 255): CONST SkyBlue = 210~%%
  508.     _PALETTECOLOR 211, _RGBA32(106, 90, 205, 255): CONST SlateBlue = 211~%%
  509.     _PALETTECOLOR 212, _RGBA32(112, 128, 144, 255): CONST SlateGray = 212~%%
  510.     _PALETTECOLOR 213, _RGBA32(255, 250, 250, 255): CONST Snow = 213~%%
  511.     _PALETTECOLOR 214, _RGBA32(0, 255, 127, 255): CONST SpringGreen = 214~%%
  512.     _PALETTECOLOR 215, _RGBA32(70, 130, 180, 255): CONST SteelBlue = 215~%%
  513.     _PALETTECOLOR 216, _RGBA32(255, 207, 72, 255): CONST Sunglow = 216~%%
  514.     _PALETTECOLOR 217, _RGBA32(253, 94, 83, 255): CONST SunsetOrange = 217~%%
  515.     _PALETTECOLOR 218, _RGBA32(210, 180, 140, 255): CONST Tann = 218~%%
  516.     _PALETTECOLOR 219, _RGBA32(0, 128, 128, 255): CONST Teal = 219~%%
  517.     _PALETTECOLOR 220, _RGBA32(24, 167, 181, 255): CONST TealBlue = 220~%%
  518.     _PALETTECOLOR 221, _RGBA32(216, 191, 216, 255): CONST Thistle = 221~%%
  519.     _PALETTECOLOR 222, _RGBA32(252, 137, 172, 255): CONST TickleMePink = 222~%%
  520.     _PALETTECOLOR 223, _RGBA32(219, 215, 210, 255): CONST Timberwolf = 223~%%
  521.     _PALETTECOLOR 224, _RGBA32(255, 99, 71, 255): CONST Tomato = 224~%%
  522.     _PALETTECOLOR 225, _RGBA32(23, 128, 109, 255): CONST TropicalRainForest = 225~%%
  523.     _PALETTECOLOR 226, _RGBA32(222, 170, 136, 255): CONST Tumbleweed = 226~%%
  524.     _PALETTECOLOR 227, _RGBA32(64, 224, 208, 255): CONST Turquoise = 227~%%
  525.     _PALETTECOLOR 228, _RGBA32(119, 221, 231, 255): CONST TurquoiseBlue = 228~%%
  526.     _PALETTECOLOR 229, _RGBA32(255, 255, 102, 255): CONST UnmellowYellow = 229~%%
  527.     _PALETTECOLOR 230, _RGBA32(238, 130, 238, 255): CONST Violet = 230~%%
  528.     _PALETTECOLOR 231, _RGBA32(50, 74, 178, 255): CONST VioletBlue = 231~%%
  529.     _PALETTECOLOR 232, _RGBA32(247, 83, 148, 255): CONST VioletRed = 232~%%
  530.     _PALETTECOLOR 233, _RGBA32(255, 160, 137, 255): CONST VividTangerine = 233~%%
  531.     _PALETTECOLOR 234, _RGBA32(143, 80, 157, 255): CONST VividViolet = 234~%%
  532.     _PALETTECOLOR 235, _RGBA32(245, 222, 179, 255): CONST Wheat = 235~%%
  533.     _PALETTECOLOR 236, _RGBA32(245, 245, 245, 255): CONST Whitesmoke = 236~%%
  534.     _PALETTECOLOR 237, _RGBA32(162, 173, 208, 255): CONST WildBlueYonder = 237~%%
  535.     _PALETTECOLOR 238, _RGBA32(255, 67, 164, 255): CONST WildStrawberry = 238~%%
  536.     _PALETTECOLOR 239, _RGBA32(252, 108, 133, 255): CONST WildWatermelon = 239~%%
  537.     _PALETTECOLOR 240, _RGBA32(205, 164, 222, 255): CONST Wisteria = 240~%%
  538.     _PALETTECOLOR 241, _RGBA32(154, 205, 50, 255): CONST YellowGreen = 241~%%
  539.     _PALETTECOLOR 242, _RGBA32(255, 174, 66, 255): CONST YellowOrange = 242~%%
  540.  
  541.  
  542.  
  543. ''$INCLUDE:'LinkedList.BI
  544.  
  545. CONST True = -1, False = 0
  546. CONST Left = 1, Right = 2, Middle = 3, Center = 3
  547. CONST None = 0, Alpha = 1, Numeric = 2, NoCase = 4, Reverse = 8
  548. CONST LeftClick = 1, RightClick = 2, LeftDown = 4, RightDown = 8, Hover = 16
  549.  
  550. TYPE MenuType
  551.     Valid AS _BYTE
  552.     Visible AS _BYTE
  553.     ScrollBarHidden AS _BYTE
  554.     Top AS INTEGER
  555.     Left AS INTEGER
  556.     Height AS INTEGER
  557.     Frame AS _BYTE
  558.     BorderColor AS _UNSIGNED LONG
  559.     BackgroundColor AS _UNSIGNED LONG
  560.     Header AS _BYTE
  561.     Caption AS STRING * 255
  562.     CC AS _UNSIGNED LONG 'caption color
  563.     CBG AS _UNSIGNED LONG 'caption background color
  564.     HighLightColor AS _UNSIGNED LONG
  565.     Exit AS _BYTE
  566.     Entries AS INTEGER
  567.     TopEntry AS INTEGER
  568.     ListColor AS _UNSIGNED LONG
  569.     ListBackground AS _UNSIGNED LONG
  570.     ListJustify AS _BYTE
  571.  
  572. DIM SHARED MenusActive AS LONG
  573. REDIM SHARED Menu(10) AS MenuType
  574. REDIM SHARED MenuList(32767, 10) AS STRING 'Up to 32,767 items max in our list.
  575. REDIM SHARED MenuListDisabled(32767, 10) AS _BYTE
  576. REDIM SHARED MenuDisplayOrder(32767, 10) AS INTEGER
  577. TYPE LinkType
  578.     one AS LONG
  579.     another AS LONG
  580. REDIM SHARED LinkedTo(1000) AS LinkType
  581. DIM SHARED ScrollDelay AS _FLOAT
  582. DIM SHARED MouseScroll AS INTEGER
  583.  
  584. 'Before here goes BI file content
  585. 'After here goes working program
  586.  
  587. DEFLNG A-Z
  588. SCREEN _NEWIMAGE(800, 600, 32)
  589.  
  590. MainMenu = GetMenuHandle
  591. SetMenuSize MainMenu, 200, 150
  592. SetMenuPosition MainMenu, 100, 100
  593. SetMenuFrame MainMenu, True, Red, Yellow
  594. SetMenuVisible MainMenu, True
  595. SetMenuCaption MainMenu, True, "Name", Black, White, True
  596. SetMenuListProperties MainMenu, Black, 0, Center 'Right 'Left
  597. SetMenuHighLightColor MainMenu, Red
  598. FOR i = 1 TO 23
  599.     READ n$
  600.     AddMenuItem MainMenu, n$
  601.  
  602. DATA Steve,Pete,Bob,Joe,Fred
  603. DATA Sam,One,Two,Three,Four
  604. DATA Five,Six,Seven,Eight,Nine
  605. DATA These,are,all,my,names
  606. DATA "Aren't",they,grand
  607.  
  608. SecondMenu = GetMenuHandle
  609. SetMenuSize SecondMenu, 100, 150
  610. SetMenuPosition SecondMenu, 300, 100
  611. SetMenuFrame SecondMenu, True, Red, Yellow
  612. SetMenuVisible SecondMenu, True
  613. SetMenuCaption SecondMenu, True, "Age", Black, White, True
  614. SetMenuListProperties SecondMenu, Black, 0, Left
  615. SetMenuHighLightColor SecondMenu, Red
  616.  
  617. FOR i = 1 TO 23
  618.     READ n$
  619.     AddMenuItem SecondMenu, n$
  620.  
  621. DATA 12,23,34,45,56
  622. DATA 67,78,89,90,1
  623. DATA 9,98,87,76,65
  624. DATA 54,43,32,21,10
  625. DATA 42,55,12
  626.  
  627. sortmode = 0: linked = -1: menuon = 1
  628.  
  629. HideMenuScrollBar MainMenu
  630. LinkMenus MainMenu, SecondMenu
  631.  
  632. DisableItem MainMenu, 5
  633. ScrollDelay = .25
  634.     CLS
  635.     LOCATE 20, 1: PRINT "Press <H> to hide the menu."
  636.     PRINT "Press <S> to show the menu."
  637.     PRINT "Press <N> for No Sort order."
  638.     PRINT "Press <A> for Alphabetic Sort order."
  639.     PRINT "Press <#> for Numeric Sort order."
  640.     PRINT "Press <C> to toggle case sorting."
  641.     PRINT "Press <R> to toggle reverse sorting."
  642.     PRINT "Press <L> to link the menus."
  643.     PRINT "Press <U> to unlink the menus."
  644.     PRINT "Press <TAB> to swap between menus."
  645.     PRINT "<ESC> to quit"
  646.     PRINT
  647.     PRINT "Currently: ";
  648.     IF sortmode AND 1 THEN
  649.         PRINT "ALPHA SORT";
  650.         IF kase THEN PRINT ", CASE-SENSITIVE";
  651.         IF reversed THEN PRINT ", REVERSE-ORDER" ELSE PRINT
  652.     ELSEIF sortmode AND 2 THEN
  653.         PRINT "NUMERIC SORT";
  654.         IF reversed THEN PRINT ", REVERSE-ORDER" ELSE PRINT
  655.     ELSE
  656.         PRINT "NOT SORTING"
  657.     END IF
  658.     LOCATE 5, 25
  659.     IF linked THEN PRINT "LINKED LISTS" ELSE PRINT "UNLINKED LISTS"
  660.     LOCATE 6, 15: PRINT "MENU ASSOCIATED WITH KEYBOARD: "; menuon
  661.  
  662.     MouseScroll = 0
  663.         MouseScroll = MouseScroll + _MOUSEWHEEL
  664.     WEND
  665.  
  666.     k = _KEYHIT
  667.     SELECT CASE k
  668.         CASE ASC("L"), ASC("l"): LinkMenus MainMenu, SecondMenu: linked = -1
  669.         CASE ASC("U"), ASC("u"): UnLinkMenus MainMenu, SecondMenu: linked = 0
  670.         CASE ASC("H"), ASC("h"): HideMenu menuon
  671.         CASE ASC("S"), ASC("s"): ShowMenu menuon
  672.         CASE ASC("N"), ASC("n"): sortmode = None: changed = -1: reversed = 0: kase = 0
  673.         CASE ASC("A"), ASC("a"): sortmode = Alpha: changed = -1
  674.         CASE ASC("#"), ASC("3"): sortmode = Numeric: changed = -1
  675.         CASE ASC("C"), ASC("c"): kase = NOT kase: changed = -1
  676.         CASE ASC("R"), ASC("r"): reversed = NOT reversed: changed = -1
  677.         CASE 9: menuon = menuon + 1: IF menuon = 3 THEN menuon = 1
  678.         CASE 27: SYSTEM
  679.     END SELECT
  680.     IF changed THEN
  681.         IF sortmode <> 0 THEN
  682.             IF kase THEN sortmode = sortmode OR NoCase ELSE sortmode = sortmode AND NOT NoCase
  683.             IF reversed THEN sortmode = sortmode OR Reverse ELSE sortmode = sortmode AND NOT Reverse
  684.         END IF
  685.         MenuDisplaySort menuon, sortmode
  686.         changed = 0
  687.     END IF
  688.     DisplayMenus
  689.     CheckMenus MouseStatus, MenuSelected, OptionSelected
  690.     IF MouseStatus <> 0 AND MenuSelected <> 0 THEN
  691.         IF MouseStatus AND LeftClick THEN
  692.             LOCATE 1, 1
  693.             PRINT "You LEFT CLICKED Option #"; OptionSelected; " in Menu #"; MenuSelected
  694.             PRINT "Which was: "; GetListItem(MenuSelected, OptionSelected)
  695.             PRINT
  696.             IF linked THEN
  697.                 PRINT "Since our lists are linked, we get the following items:"; GetListItem(1, OptionSelected), GetListItem(2, OptionSelected)
  698.             ELSE
  699.                 PRINT "Since our lists are unlinked, we get the following items:"; GetListItem(MenuSelected, OptionSelected)
  700.             END IF
  701.             _DISPLAY
  702.             _DELAY 2 'give it time to pop up
  703.         ELSEIF MouseStatus AND RightClick THEN
  704.             LOCATE 1, 1
  705.             PRINT "You RIGHT CLICKED Option #"; OptionSelected; " in Menu #"; MenuSelected
  706.             PRINT "Which was: "; GetListItem(MenuSelected, OptionSelected)
  707.             PRINT
  708.             IF linked THEN
  709.                 PRINT "Since our lists are linked, we get the following items:"; GetListItem(1, OptionSelected), GetListItem(2, OptionSelected)
  710.             ELSE
  711.                 PRINT "Since our lists are unlinked, we get the following items:"; GetListItem(MenuSelected, OptionSelected)
  712.             END IF
  713.             _DISPLAY
  714.             _DELAY 2 'give it time to pop up
  715.         END IF
  716.         COLOR Yellow
  717.         IF MouseStatus AND LeftDown THEN LOCATE 35, 1: PRINT "LEFT MOUSE DOWN over Option #"; OptionSelected; " in Menu #"; MenuSelected
  718.         IF MouseStatus AND RightDown THEN LOCATE 35, 1: PRINT "RIGHT MOUSE DOWN over Option #"; OptionSelected; " in Menu #"; MenuSelected
  719.         COLOR Purple
  720.         IF MouseStatus AND Hover THEN LOCATE 36, 1: PRINT "HOVERING over Option #"; OptionSelected; " in Menu #"; MenuSelected;
  721.         COLOR White
  722.  
  723.     END IF
  724.     _LIMIT 30
  725.     _DISPLAY
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732. ''$INCLUDE:'LinkedList.BM'
  733.  
  734. 'And here goes the BM routines
  735.  
  736.  
  737.  
  738. SUB LinkMenus (handle1, handle2)
  739.     IF handle1 = 0 OR handle2 = 0 THEN ERROR 5: EXIT SUB
  740.     IF handle1 = handle2 THEN EXIT SUB 'Why the heck are we linking one list to itself?!
  741.     IF Menu(handle1).Valid AND Menu(handle2).Valid THEN
  742.         LinkMax = LinkedTo(0).one 'I'm using the very first entry into my array to store the number of link entries I have
  743.         'First check to see if the two menus are already linked
  744.         FOR i = 1 TO LinkMax
  745.             found = 0
  746.             IF handle1 = LinkedTo(i).one OR handle1 = LinkedTo(i).another THEN found = found + 1
  747.             IF handle2 = LinkedTo(i).one OR handle2 = LinkedTo(i).another THEN found = found + 1
  748.             IF found = 2 THEN EXIT SUB 'the two lists are already linked
  749.             IF handle1 = 0 AND handle2 = 0 AND openspot = 0 THEN openspot = i 'we found a spot where a link was freed before; let's use it
  750.         NEXT
  751.         MenuDisplaySort handle1, None: MenuDisplaySort handle2, None 'unsort the lists to begin with.
  752.         Menu(handle1).TopEntry = 1: Menu(handle2).TopEntry = 1 'and then reset them to their topmost position
  753.  
  754.         IF openspot THEN
  755.             LinkedTo(openspot).one = handle1
  756.             LinkedTo(openspot).another = handle2
  757.         ELSE
  758.             LinkMax = LinkMax + 1: LinkedTo(0).one = LinkMax
  759.             LinkedTo(LinkMax).one = handle1
  760.             LinkedTo(LinkMax).another = handle2
  761.         END IF
  762.     ELSE
  763.         ERROR 5
  764.     END IF
  765.  
  766. SUB UnLinkMenus (handle1, handle2)
  767.     IF handle1 = 0 OR handle2 = 0 THEN ERROR 5: EXIT SUB 'no list should be linked to 0.  0 is nothing...  Can't free a link to nothing.
  768.     IF handle1 = handle2 THEN EXIT SUB 'We can't unlink a list from itself!
  769.     IF Menu(handle1).Valid AND Menu(handle2).Valid THEN
  770.         FOR i = 1 TO LinkedTo(0).one
  771.             IF handle1 = LinkedTo(i).one OR handle1 = LinkedTo(i).another THEN found = found + 1
  772.             IF handle2 = LinkedTo(i).one OR handle2 = LinkedTo(i).another THEN found = found + 1
  773.             IF found = 2 THEN LinkedTo(i).one = 0: LinkedTo(i).another = 0 'unlink them!
  774.         NEXT
  775.     ELSE
  776.         ERROR 5
  777.     END IF
  778.  
  779. SUB DisableItem (handle, item)
  780.     IF Menu(handle).Valid THEN MenuListDisabled(item, handle) = -1 ELSE ERROR 5
  781.  
  782. SUB EnableItem (handle, item)
  783.     IF Menu(handle).Valid THEN MenuListDisabled(item, handle) = 0 ELSE ERROR 5
  784.  
  785. SUB ShowMenu (Handle)
  786.     IF Menu(Handle).Valid THEN Menu(Handle).Visible = -1 ELSE ERROR 5
  787.  
  788. SUB HideMenu (Handle)
  789.     IF Menu(Handle).Valid THEN Menu(Handle).Visible = 0 ELSE ERROR 5
  790.  
  791. SUB ShowMenuScrollBar (Handle)
  792.     IF Menu(Handle).Valid THEN Menu(Handle).ScrollBarHidden = 0 ELSE ERROR 5
  793.  
  794. SUB HideMenuScrollBar (Handle)
  795.     IF Menu(Handle).Valid THEN Menu(Handle).ScrollBarHidden = -1 ELSE ERROR 5
  796.  
  797.  
  798.  
  799. FUNCTION GetListItem$ (Handle, Item)
  800.     IF Menu(Handle).Valid THEN
  801.         IF Item < 0 OR Item > Menu(Handle).Entries THEN ERROR 5: EXIT SUB
  802.         GetListItem$ = LTRIM$(RTRIM$(MenuList(Item, Handle)))
  803.     ELSE
  804.         ERROR 5
  805.     END IF
  806.  
  807.  
  808.  
  809. SUB AddMenuItem (Handle, Item$)
  810.     IF Menu(Handle).Valid THEN
  811.         Menu(Handle).Entries = Menu(Handle).Entries + 1
  812.         MenuList(Menu(Handle).Entries, Handle) = Item$
  813.         MenuDisplayOrder(Menu(Handle).Entries, Handle) = Menu(Handle).Entries
  814.     ELSE
  815.         ERROR 5
  816.     END IF
  817.  
  818.  
  819. SUB SetMenuListProperties (Handle, ListColor AS _UNSIGNED LONG, ListBackground AS _UNSIGNED LONG, ListJustify AS _BYTE)
  820.     IF Menu(Handle).Valid THEN
  821.         Menu(Handle).ListColor = ListColor
  822.         Menu(Handle).ListBackground = ListBackground
  823.         Menu(Handle).ListJustify = ListJustify
  824.     ELSE
  825.         ERROR 5
  826.     END IF
  827.  
  828. SUB SetMenuHighLightColor (Handle, HighLightColor AS _UNSIGNED LONG)
  829.     IF Menu(Handle).Valid THEN
  830.         Menu(Handle).HighLightColor = HighLightColor
  831.     ELSE
  832.         ERROR 5
  833.     END IF
  834.  
  835.  
  836. SUB SetMenuCaption (Handle, Header, Caption AS STRING * 255, CaptionColor AS _UNSIGNED LONG, CaptionBackground AS _UNSIGNED LONG, Xit)
  837.     IF Menu(Handle).Valid THEN
  838.         Menu(Handle).Header = Header
  839.         Menu(Handle).Caption = Caption
  840.         Menu(Handle).CC = CaptionColor
  841.         Menu(Handle).CBG = CaptionBackground
  842.         Menu(Handle).Exit = Xit
  843.     ELSE
  844.         ERROR 5
  845.     END IF
  846.  
  847.  
  848. SUB SetMenuFrame (Handle, HaveFrame, FrameColor AS _UNSIGNED LONG, FrameBackGround AS _UNSIGNED LONG)
  849.     IF Menu(Handle).Valid THEN
  850.         Menu(Handle).Frame = HaveFrame
  851.         Menu(Handle).BorderColor = FrameColor
  852.         Menu(Handle).BackgroundColor = FrameBackGround
  853.     ELSE
  854.         ERROR 5
  855.     END IF
  856.  
  857.  
  858.  
  859. SUB SetMenuPosition (Handle, Left, Top)
  860.     IF Menu(Handle).Valid THEN
  861.         'some basic error checking
  862.         IF Top < 0 THEN ERROR 5: EXIT SUB 'Let's try and keep the menu on the screen, why don't we
  863.         IF Left < 0 THEN ERROR 5: EXIT SUB
  864.         IF Left > _WIDTH THEN ERROR 5: EXIT SUB
  865.         IF Top > _HEIGHT THEN ERROR 5: EXIT SUB
  866.         Menu(Handle).Left = Left
  867.         Menu(Handle).Top = Top
  868.     ELSE
  869.         ERROR 5 'toss a generic error if the handle is bad
  870.         'I can add a custom error pop up routine later with appropiate messages
  871.     END IF
  872.  
  873.  
  874. SUB SetMenuVisible (Handle, Visible)
  875.     IF Menu(Handle).Valid THEN Menu(Handle).Visible = Visible ELSE ERROR 5
  876.  
  877. SUB SetMenuSize (Handle, Width, Height)
  878.     IF Menu(Handle).Valid THEN
  879.         'some basic error checking
  880.         IF Width < _FONTWIDTH THEN ERROR 5: EXIT SUB 'Can't we at least make a menu which will hold a single character?!
  881.         IF Height < _FONTHEIGHT THEN ERROR 5: EXIT SUB
  882.         IF Width > _WIDTH THEN ERROR 5: EXIT SUB 'And let's not make it generally larger than our screen, why don't we?!
  883.         IF Height > _HEIGHT THEN ERROR 5: EXIT SUB
  884.         Menu(Handle).Width = Width
  885.         Menu(Handle).Height = Height
  886.     ELSE
  887.         ERROR 5 'toss a generic error if the handle is bad
  888.         'I can add a custom error pop up routine later with appropiate messages
  889.     END IF
  890.  
  891. FUNCTION GetMenuHandle&
  892.     FOR i = 1 TO MenusActive
  893.         IF Menu(i).Valid = 0 THEN found = i: EXIT FOR
  894.     NEXT
  895.     IF NOT found THEN
  896.         MenusActive = MenusActive + 1
  897.         found = MenusActive
  898.         u = UBOUND(menu)
  899.         DO UNTIL MenusActive < u
  900.             REDIM _PRESERVE Menu(u + 10) AS MenuType
  901.             REDIM _PRESERVE MenuList(32767, u + 10) AS STRING
  902.             REDIM _PRESERVE MenuDisplayOrder(32767, u + 10) AS INTEGER
  903.             REDIM _PRESERVE MenuListDisabled(32767, u + 10) AS _BYTE
  904.             u = UBOUND(menu)
  905.         LOOP
  906.     END IF
  907.     GetMenuHandle& = found
  908.     Menu(found).Valid = -1 'and let's make this a valid handle
  909.  
  910.  
  911. SUB CheckMenus (MouseStatus AS LONG, MenuSelected AS LONG, OptionSelected AS LONG)
  912.  
  913.     MenuSelected = 0: OptionSelected = 0
  914.     FOR i = 1 TO MenusActive
  915.         IF Menu(i).Visible AND Menu(i).Valid THEN
  916.             IF startnum = 0 THEN startnum = i
  917.             ProcessMenu i, startnum, MouseStatus, MenuSelected, OptionSelected
  918.             IF MenuSelected THEN EXIT SUB
  919.         END IF
  920.     NEXT
  921.  
  922.  
  923. SUB DisplayMenus
  924.     FOR Whichone = 1 TO MenusActive
  925.         IF Menu(Whichone).Visible THEN
  926.             'Get the starting limits of where menu/list text can appear
  927.             x1 = Menu(Whichone).Left: x2 = x1 + Menu(Whichone).Width
  928.             y1 = Menu(Whichone).Top: y2 = Menu(Whichone).Top + Menu(Whichone).Height
  929.             caption$ = LTRIM$(RTRIM$(Menu(Whichone).Caption)) 'strip unneeded spaces from the caption (WhichOnef any)
  930.  
  931.             'clear the background
  932.             LINE (Menu(Whichone).Left, Menu(Whichone).Top)-STEP(Menu(Whichone).Width, Menu(Whichone).Height), Menu(Whichone).BackgroundColor, BF
  933.             'draw the frame; adjust text limits
  934.             IF Menu(Whichone).Frame THEN
  935.                 LINE (Menu(Whichone).Left, Menu(Whichone).Top)-STEP(Menu(Whichone).Width, Menu(Whichone).Height), Menu(Whichone).BorderColor, B
  936.                 x1 = x1 + 1: y1 = y1 + 1
  937.                 x2 = x2 - 1: y2 = y2 - 1
  938.             END IF
  939.             IF Menu(Whichone).Header THEN
  940.                 temp = x2 - x1 + 1
  941.                 LINE (x1, y1)-(x2, y1 + _FONTHEIGHT), Menu(Whichone).CBG, BF
  942.                 IF Menu(Whichone).Exit THEN
  943.                     temp = temp - _FONTWIDTH * 2
  944.                     ex1 = x2 - 1 - _FONTWIDTH: ex2 = ex1 + _FONTWIDTH
  945.                     ey1 = y1 + 1: ey2 = ey1 + _FONTHEIGHT - 3
  946.                     LINE (ex1, ey1)-(ex2, ey2), Red, BF
  947.                     LINE (ex1, ey1)-(ex2, ey2), Black
  948.                     LINE (ex1, ey2)-(ex2, ey1), Black
  949.                 END IF
  950.                 DO UNTIL _PRINTWIDTH(caption$) <= temp
  951.                     caption$ = LEFT$(caption$, LEN(caption$) - 1)
  952.                 LOOP
  953.                 COLOR Menu(Whichone).CC, Menu(Whichone).CBG
  954.                 _PRINTSTRING (x1 + (temp - _PRINTWIDTH(caption$)) \ 2, y1), caption$
  955.                 y1 = y1 + _FONTHEIGHT
  956.                 IF Menu(Whichone).Frame THEN
  957.                     LINE (x1, y1)-(x2, y1), Menu(Whichone).BorderColor
  958.                     y1 = y1 + 2
  959.                 END IF
  960.             END IF 'end header creation
  961.  
  962.             IF Menu(Whichone).Entries > 0 THEN 'We have items in our list to display!
  963.                 IF Menu(Whichone).TopEntry < 1 THEN Menu(Whichone).TopEntry = 1 'check to make certain we're displaying from the first entry on at least
  964.                 IF Menu(Whichone).TopEntry > Menu(Whichone).Entries THEN Menu(Whichone).TopEntry = Menu(Whichone).Entries
  965.                 printlimit = (x2 - x1 + 1) \ _FONTWIDTH
  966.                 limitfound = 1 + (y2 - y1 + 1) \ _FONTHEIGHT - 1
  967.                 IF limitfound > Menu(Whichone).Entries THEN
  968.                     limitfound = Menu(Whichone).Entries
  969.                 ELSE
  970.                     scrollneeded = -1
  971.                     printlimit = printlimit - 1
  972.                 END IF
  973.                 COLOR Menu(Whichone).ListColor, Menu(Whichone).ListBackground
  974.                 IF Menu(Whichone).ScrollBarHidden = -1 THEN scrollneeded = 0
  975.                 DIM r AS _UNSIGNED _BYTE, g AS _UNSIGNED _BYTE, b AS _UNSIGNED _BYTE
  976.                 DIM CC AS INTEGER
  977.  
  978.                 r = _RED32(Menu(Whichone).BackgroundColor)
  979.                 g = _GREEN32(Menu(Whichone).BackgroundColor)
  980.                 b = _BLUE32(Menu(Whichone).BackgroundColor)
  981.                 Fade& = _RGBA32(r, g, b, 180)
  982.  
  983.                 SELECT CASE Menu(Whichone).ListJustify
  984.                     CASE Left
  985.                         FOR j = 1 TO limitfound
  986.                             CC = MenuDisplayOrder(Menu(Whichone).TopEntry + j - 1, Whichone) 'currentchoice
  987.                             graybox = 0
  988.                             t$ = RTRIM$(LTRIM$(MenuList(CC, Whichone)))
  989.                             IF MenuListDisabled(CC, Whichone) THEN graybox = -1
  990.                             FOR ii = 1 TO LinkedTo(0).one
  991.                                 IF Whichone = LinkedTo(ii).one AND MenuListDisabled(CC, LinkedTo(ii).another) THEN graybox = -1
  992.                                 IF Whichone = LinkedTo(ii).another AND MenuListDisabled(CC, LinkedTo(ii).one) THEN graybox = -1
  993.                             NEXT
  994.                             t$ = LEFT$(t$, printlimit)
  995.                             _PRINTSTRING (x1, y1 + (j - 1) * _FONTHEIGHT), t$
  996.                             IF graybox THEN LINE (x1, y1 + (j - 1) * _FONTHEIGHT)-(x2, y1 + (j) * _FONTHEIGHT), Fade&, BF
  997.                         NEXT
  998.                     CASE Right
  999.                         FOR j = 1 TO limitfound
  1000.                             CC = MenuDisplayOrder(Menu(Whichone).TopEntry + j - 1, Whichone) 'currentchoice
  1001.                             graybox = 0
  1002.                             t$ = RTRIM$(LTRIM$(MenuList(MenuDisplayOrder(Menu(Whichone).TopEntry + j - 1, Whichone), Whichone)))
  1003.                             IF MenuListDisabled(CC, Whichone) THEN graybox = -1
  1004.                             FOR ii = 1 TO LinkedTo(0).one
  1005.                                 IF Whichone = LinkedTo(ii).one AND MenuListDisabled(CC, LinkedTo(ii).another) THEN graybox = -1
  1006.                                 IF Whichone = LinkedTo(ii).another AND MenuListDisabled(CC, LinkedTo(ii).one) THEN graybox = -1
  1007.                             NEXT
  1008.  
  1009.                             t$ = LTRIM$(LEFT$(t$, printlimit))
  1010.                             p = _PRINTWIDTH(t$)
  1011.                             IF scrollneeded THEN
  1012.                                 _PRINTSTRING (x2 - p - _FONTWIDTH, y1 + (j - 1) * _FONTHEIGHT), t$
  1013.                             ELSE
  1014.                                 _PRINTSTRING (x2 - p, y1 + (j - 1) * _FONTHEIGHT), t$
  1015.                             END IF
  1016.                             IF graybox THEN LINE (x1, y1 + (j - 1) * _FONTHEIGHT)-(x2, y1 + (j) * _FONTHEIGHT), Fade&, BF
  1017.                         NEXT
  1018.                     CASE Center
  1019.                         FOR j = 1 TO limitfound
  1020.                             CC = MenuDisplayOrder(Menu(Whichone).TopEntry + j - 1, Whichone) 'currentchoice
  1021.                             graybox = 0
  1022.                             t$ = LTRIM$(MenuList(MenuDisplayOrder(Menu(Whichone).TopEntry + j - 1, Whichone), Whichone))
  1023.                             IF MenuListDisabled(CC, Whichone) THEN graybox = -1
  1024.                             FOR ii = 1 TO LinkedTo(0).one
  1025.                                 IF Whichone = LinkedTo(ii).one AND MenuListDisabled(CC, LinkedTo(ii).another) THEN graybox = -1
  1026.                                 IF Whichone = LinkedTo(ii).another AND MenuListDisabled(CC, LinkedTo(ii).one) THEN graybox = -1
  1027.                             NEXT
  1028.                             t$ = LTRIM$(RTRIM$(LEFT$(t$, printlimit)))
  1029.                             p = _PRINTWIDTH(t$)
  1030.                             _PRINTSTRING ((x2 - x1 + 1) - p \ 2, y1 + (j - 1) * _FONTHEIGHT), t$
  1031.                             IF graybox THEN LINE (x1, y1 + (j - 1) * _FONTHEIGHT)-(x2, y1 + (j) * _FONTHEIGHT), Fade&, BF
  1032.                         NEXT
  1033.                     CASE ELSE
  1034.                         FOR j = 1 TO limitfound
  1035.                             CC = MenuDisplayOrder(Menu(Whichone).TopEntry + j - 1, Whichone) 'currentchoice
  1036.                             graybox = 0
  1037.                             t$ = RTRIM$(LTRIM$(MenuList(CC, Whichone)))
  1038.                             IF MenuListDisabled(CC, Whichone) THEN graybox = -1
  1039.                             FOR ii = 1 TO LinkedTo(0).one
  1040.                                 IF Whichone = LinkedTo(ii).one AND MenuListDisabled(CC, LinkedTo(ii).another) THEN graybox = -1
  1041.                                 IF Whichone = LinkedTo(ii).another AND MenuListDisabled(CC, LinkedTo(ii).one) THEN graybox = -1
  1042.                             NEXT
  1043.                             t$ = LEFT$(t$, printlimit)
  1044.                             _PRINTSTRING (x1, y1 + (j - 1) * _FONTHEIGHT), t$
  1045.                             IF graybox THEN LINE (x1, y1 + (j - 1) * _FONTHEIGHT)-(x2, y1 + (j) * _FONTHEIGHT), Fade&, BF
  1046.                         NEXT
  1047.                         Menu(Whichone).ListJustify = Left 'If it's not specified for some reason, let's make it left justified as default
  1048.                 END SELECT
  1049.             END IF 'end of displaying items
  1050.             IF scrollneeded THEN 'then we need a vertical scroll bar
  1051.                 barx1 = x2 - _FONTWIDTH - 1
  1052.                 barx2 = barx1 + _FONTWIDTH
  1053.                 LINE (barx1, y1)-(barx2, y2), LightGray, BF
  1054.                 COLOR Black, DarkGray
  1055.                 _PRINTSTRING (barx1, y1), ""
  1056.                 _PRINTSTRING (barx1, y2 - _FONTHEIGHT), ""
  1057.             END IF
  1058.         END IF
  1059.     NEXT
  1060.     COLOR FC, BG
  1061.  
  1062.  
  1063.  
  1064. SUB ProcessMenu (WhichOne AS LONG, StartNum AS LONG, MouseStatus AS LONG, MenuSelected AS LONG, OptionSelected AS LONG)
  1065.     STATIC OldMouse AS _BYTE, ElapsedTimer AS _FLOAT, Click AS _BYTE
  1066.     STATIC ScrollAble AS _BYTE, OldMouse2 AS _BYTE, Click2 AS _BYTE
  1067.     MX = _MOUSEX: MY = _MOUSEY: MB = _MOUSEBUTTON(1): MB2 = _MOUSEBUTTON(2)
  1068.     IF ScrollDelay < 0 THEN ScrollDelay = 0
  1069.  
  1070.     'Get the starting limits of where menu/list text can appear
  1071.     x1 = Menu(WhichOne).Left: x2 = x1 + Menu(WhichOne).Width
  1072.     y1 = Menu(WhichOne).Top: y2 = Menu(WhichOne).Top + Menu(WhichOne).Height
  1073.     IF WhichOne = StartNum THEN
  1074.         IF OldMouse = 0 AND MB = -1 THEN Click = -1 ELSE Click = 0
  1075.         IF OldMouse2 = 0 AND MB2 = -1 THEN Click2 = -1 ELSE Click2 = 0
  1076.         OldMouse = MB: OldMouse2 = MB2
  1077.         IF ElapsedTimer + ScrollDelay < TIMER(0.01) THEN
  1078.             ElapsedTimer = TIMER(0.01)
  1079.             ScrollAble = -1
  1080.         ELSE
  1081.             ScrollAble = 0
  1082.         END IF
  1083.     END IF
  1084.  
  1085.  
  1086.  
  1087.  
  1088.     IF Menu(WhichOne).Frame THEN
  1089.         LINE (Menu(WhichOne).Left, Menu(WhichOne).Top)-STEP(Menu(WhichOne).Width, Menu(WhichOne).Height), Menu(WhichOne).BorderColor, B
  1090.         x1 = x1 + 1: y1 = y1 + 1
  1091.         x2 = x2 - 1: y2 = y2 - 1
  1092.     END IF
  1093.     IF Menu(WhichOne).Header THEN
  1094.         temp = x2 - x1 + 1
  1095.         IF Menu(WhichOne).Exit THEN
  1096.             temp = temp - _FONTWIDTH * 2
  1097.             ex1 = x2 - 1 - _FONTWIDTH: ex2 = ex1 + _FONTWIDTH
  1098.             ey1 = y1 + 1: ey2 = ey1 + _FONTHEIGHT - 3
  1099.         END IF
  1100.         y1 = y1 + _FONTHEIGHT
  1101.         IF Menu(WhichOne).Frame THEN y1 = y1 + 2
  1102.     END IF 'end header creation
  1103.  
  1104.     IF Menu(WhichOne).Entries > 0 THEN 'We have items in our list to display!
  1105.         IF Menu(WhichOne).TopEntry < 1 THEN Menu(WhichOne).TopEntry = 1 'check to make certain we're displaying from the first entry on at least
  1106.         IF Menu(WhichOne).TopEntry > Menu(WhichOne).Entries THEN Menu(WhichOne).TopEntry = Menu(WhichOne).Entries
  1107.         printlimit = (x2 - x1 + 1) \ _FONTWIDTH
  1108.         limitfound = 1 + (y2 - y1 + 1) \ _FONTHEIGHT - 1
  1109.         IF limitfound > Menu(WhichOne).Entries THEN
  1110.             limitfound = Menu(WhichOne).Entries
  1111.         ELSE
  1112.             scrollneeded = -1
  1113.             printlimit = printlimit - 1
  1114.         END IF
  1115.     END IF 'end of displaying items
  1116.  
  1117.     IF Menu(WhichOne).ScrollBarHidden = -1 THEN scrollneeded = 0
  1118.  
  1119.     IF scrollneeded THEN 'then we need a vertical scroll bar
  1120.         barx1 = x2 - _FONTWIDTH - 1
  1121.         barx2 = barx1 + _FONTWIDTH
  1122.     END IF
  1123.  
  1124.  
  1125.     SELECT CASE MY 'let's determine which line we clicked the mouse on
  1126.         CASE IS < ey1 'do nothing as it's too far up the screen to be a click in this box
  1127.         CASE IS > y2 'do nothing again as it's too far down the screen to be a click in this box
  1128.         CASE ey1 TO ey2 'we've clicked on the line where the EXIT button might exist
  1129.         CASE y1 TO y2
  1130.     END SELECT
  1131.  
  1132.  
  1133.  
  1134.     SELECT CASE MY 'let's determine which line we clicked the mouse on
  1135.         CASE IS < ey1 'do nothing as it's too far up the screen to be a click in this box
  1136.         CASE IS > y2 'do nothing again as it's too far down the screen to be a click in this box
  1137.         CASE ey1 TO ey2 'we've clicked on the line where the EXIT button might exist
  1138.             IF Click AND Menu(WhichOne).Exit THEN
  1139.                 IF MX >= ex1 AND MX <= ex2 THEN Menu(WhichOne).Visible = False 'If the exit button is available, and we click it, it closes the menu/list
  1140.             END IF
  1141.         CASE y1 TO y2
  1142.             done = 0
  1143.             IF barx1 > 0 THEN p2 = barx1 - 1 ELSE p2 = x2
  1144.             IF MX >= x1 AND MX <= p2 THEN 'highlight the choice the user is over
  1145.                 yPOS = ((MY - y1 + 1) \ _FONTHEIGHT) * _FONTHEIGHT + y1
  1146.                 IF yPOS + _FONTHEIGHT <= y2 THEN LINE (x1, yPOS)-(p2, yPOS + _FONTHEIGHT), Menu(WhichOne).HighLightColor, B
  1147.             END IF
  1148.  
  1149.             IF MouseScroll THEN
  1150.                 IF MX >= x1 AND MX <= x2 THEN
  1151.                     Menu(WhichOne).TopEntry = Menu(WhichOne).TopEntry + MouseScroll
  1152.                     IF Menu(WhichOne).TopEntry < 1 THEN Menu(WhichOne).TopEntry = 1
  1153.                     IF Menu(WhichOne).TopEntry > Menu(WhichOne).Entries - limitfound + 1 THEN Menu(WhichOne).TopEntry = Menu(WhichOne).Entries - limitfound + 1
  1154.                     FOR i = 1 TO LinkedTo(0).one
  1155.                         IF WhichOne = LinkedTo(i).one THEN Menu(LinkedTo(i).another).TopEntry = Menu(WhichOne).TopEntry
  1156.                         IF WhichOne = LinkedTo(i).another THEN Menu(LinkedTo(i).one).TopEntry = Menu(WhichOne).TopEntry
  1157.                     NEXT
  1158.                 END IF
  1159.             END IF
  1160.  
  1161.             IF scrollneeded THEN
  1162.                 IF MY >= y1 AND MY <= y1 + _FONTHEIGHT AND MX >= barx1 AND MX <= barx2 AND MB <> 0 THEN 'it's the top scroll bar
  1163.                     IF ScrollAble THEN Menu(WhichOne).TopEntry = Menu(WhichOne).TopEntry - 1
  1164.                     IF Menu(WhichOne).TopEntry < 1 THEN Menu(WhichOne).TopEntry = 1
  1165.                     done = -1
  1166.                     FOR i = 1 TO LinkedTo(0).one
  1167.                         IF WhichOne = LinkedTo(i).one THEN Menu(LinkedTo(i).another).TopEntry = Menu(WhichOne).TopEntry
  1168.                         IF WhichOne = LinkedTo(i).another THEN Menu(LinkedTo(i).one).TopEntry = Menu(WhichOne).TopEntry
  1169.                     NEXT
  1170.                 ELSEIF MY >= y2 - _FONTHEIGHT AND MY <= y2 AND MX >= barx1 AND MX <= barx2 AND MB <> 0 THEN 'it's the bottom scroll bar
  1171.                     IF ScrollAble THEN Menu(WhichOne).TopEntry = Menu(WhichOne).TopEntry + 1
  1172.                     IF Menu(WhichOne).TopEntry > Menu(WhichOne).Entries - limitfound + 1 THEN Menu(WhichOne).TopEntry = Menu(WhichOne).Entries - limitfound + 1
  1173.                     done = -1
  1174.                     FOR i = 1 TO LinkedTo(0).one
  1175.                         IF WhichOne = LinkedTo(i).one THEN Menu(LinkedTo(i).another).TopEntry = Menu(WhichOne).TopEntry
  1176.                         IF WhichOne = LinkedTo(i).another THEN Menu(LinkedTo(i).one).TopEntry = Menu(WhichOne).TopEntry
  1177.                     NEXT
  1178.                 ELSEIF MX >= barx1 AND MX <= barx2 AND MB <> 0 THEN
  1179.                     MenuLimit = Menu(WhichOne).Entries - limitfound + 2
  1180.                     ylimit = y2 - y1 - _FONTHEIGHT * 2 + 1
  1181.                     yPOS = MY - y1 - _FONTHEIGHT + 1
  1182.                     Menu(WhichOne).TopEntry = (MenuLimit - (ylimit - yPOS) / ylimit * MenuLimit)
  1183.                     IF Menu(WhichOne).TopEntry >= MenuLimit THEN Menu(WhichOne).TopEntry = MenuLimit - 1
  1184.                     done = -1
  1185.                     FOR i = 1 TO LinkedTo(0).one
  1186.                         IF WhichOne = LinkedTo(i).one THEN Menu(LinkedTo(i).another).TopEntry = Menu(WhichOne).TopEntry
  1187.                         IF WhichOne = LinkedTo(i).another THEN Menu(LinkedTo(i).one).TopEntry = Menu(WhichOne).TopEntry
  1188.                     NEXT
  1189.                 END IF
  1190.             END IF
  1191.  
  1192.             IF NOT done THEN 'if we've processed a scrollbar event, we're finished
  1193.                 IF MX >= x1 AND MX <= x2 THEN
  1194.                     MenuSelected = WhichOne
  1195.                     OptionSelected = MenuDisplayOrder((MY - y1 + 1) \ _FONTHEIGHT + Menu(WhichOne).TopEntry, WhichOne)
  1196.                     invalidate = 0
  1197.                     IF MenuListDisabled(OptionSelected, WhichOne) THEN invalidate = -1
  1198.                     FOR ii = 1 TO LinkedTo(0).one
  1199.                         IF WhichOne = LinkedTo(ii).one AND MenuListDisabled(OptionSelected, LinkedTo(ii).another) THEN invalidate = -1
  1200.                         IF WhichOne = LinkedTo(ii).another AND MenuListDisabled(OptionSelected, LinkedTo(ii).one) THEN invalidate = -1
  1201.                     NEXT
  1202.                     IF barx1 <> 0 AND MX > barx1 THEN invalidate = -1
  1203.                     IF invalidate THEN MenuSelected = 0: OptionSelected = 0
  1204.                 END IF
  1205.             END IF
  1206.     END SELECT
  1207.  
  1208.  
  1209.     MouseStatus = 0
  1210.     MouseStatus = MouseStatus OR -Click 'leftclick
  1211.     MouseStatus = MouseStatus OR Click2 * -2 'rightclick
  1212.     MouseStatus = MouseStatus OR _MOUSEBUTTON(1) * -4 'leftdown
  1213.     MouseStatus = MouseStatus OR _MOUSEBUTTON(2) * -8 'rightdown
  1214.     MouseStatus = MouseStatus OR (MenuSelected <> 0) * 16 'If we're over the menu, we're hovering
  1215.  
  1216.  
  1217.  
  1218. SUB MenuDisplaySort (handle AS LONG, sortmethod AS _BYTE)
  1219.     gap = Menu(handle).Entries
  1220.  
  1221.     IF sortmethod AND Alpha THEN
  1222.         IF sortmethod AND NoCase THEN
  1223.             DO
  1224.                 gap = 10 * gap \ 13
  1225.                 IF gap < 1 THEN gap = 1
  1226.                 i = 0
  1227.                 swapped = 0
  1228.                 DO
  1229.                     t$ = UCASE$(LTRIM$(RTRIM$(MenuList(MenuDisplayOrder(i, handle), handle))))
  1230.                     t1$ = UCASE$(LTRIM$(RTRIM$(MenuList(MenuDisplayOrder(i + gap, handle), handle))))
  1231.                     IF t$ > t1$ THEN
  1232.                         SWAP MenuDisplayOrder(i, handle), MenuDisplayOrder(i + gap, handle)
  1233.                         FOR ii = 1 TO LinkedTo(0).one
  1234.                             IF handle = LinkedTo(ii).one THEN SWAP MenuDisplayOrder(i, LinkedTo(ii).another), MenuDisplayOrder(i + gap, LinkedTo(ii).another)
  1235.                             IF handle = LinkedTo(ii).another THEN SWAP MenuDisplayOrder(i, LinkedTo(ii).one), MenuDisplayOrder(i + gap, LinkedTo(ii).one)
  1236.                         NEXT
  1237.                         swapped = -1
  1238.                     END IF
  1239.                     i = i + 1
  1240.                 LOOP UNTIL i + gap > Menu(handle).Entries
  1241.             LOOP UNTIL gap = 1 AND swapped = 0
  1242.         ELSE
  1243.             DO
  1244.                 gap = 10 * gap \ 13
  1245.                 IF gap < 1 THEN gap = 1
  1246.                 i = 0
  1247.                 swapped = 0
  1248.                 DO
  1249.                     t$ = LTRIM$(RTRIM$(MenuList(MenuDisplayOrder(i, handle), handle)))
  1250.                     t1$ = LTRIM$(RTRIM$(MenuList(MenuDisplayOrder(i + gap, handle), handle)))
  1251.                     IF t$ > t1$ THEN
  1252.                         SWAP MenuDisplayOrder(i, handle), MenuDisplayOrder(i + gap, handle)
  1253.                         FOR ii = 1 TO LinkedTo(0).one
  1254.                             IF handle = LinkedTo(ii).one THEN SWAP MenuDisplayOrder(i, LinkedTo(ii).another), MenuDisplayOrder(i + gap, LinkedTo(ii).another)
  1255.                             IF handle = LinkedTo(ii).another THEN SWAP MenuDisplayOrder(i, LinkedTo(ii).one), MenuDisplayOrder(i + gap, LinkedTo(ii).one)
  1256.                         NEXT
  1257.                         swapped = -1
  1258.                     END IF
  1259.                     i = i + 1
  1260.                 LOOP UNTIL i + gap > Menu(handle).Entries
  1261.             LOOP UNTIL gap = 1 AND swapped = 0
  1262.         END IF
  1263.         IF sortmethod AND Reverse THEN
  1264.             FOR i = 1 TO Menu(handle).Entries \ 2
  1265.                 SWAP MenuDisplayOrder(i, handle), MenuDisplayOrder(Menu(handle).Entries - i + 1, handle)
  1266.                 FOR ii = 1 TO LinkedTo(0).one
  1267.                     IF handle = LinkedTo(ii).one THEN SWAP MenuDisplayOrder(i, LinkedTo(ii).another), MenuDisplayOrder(Menu(handle).Entries - i + 1, LinkedTo(ii).another)
  1268.                     IF handle = LinkedTo(ii).another THEN SWAP MenuDisplayOrder(i, LinkedTo(ii).one), MenuDisplayOrder(Menu(handle).Entries - i + 1, LinkedTo(ii).one)
  1269.                 NEXT
  1270.             NEXT
  1271.         END IF
  1272.     ELSEIF sortmethod AND Numeric THEN
  1273.         DO
  1274.             gap = 10 * gap \ 13
  1275.             IF gap < 1 THEN gap = 1
  1276.             i = 0
  1277.             swapped = 0
  1278.             DO
  1279.                 IF VAL(MenuList(MenuDisplayOrder(i, handle), handle)) > VAL(MenuList(MenuDisplayOrder(i + gap, handle), handle)) THEN
  1280.                     SWAP MenuDisplayOrder(i, handle), MenuDisplayOrder(i + gap, handle)
  1281.                     FOR ii = 1 TO LinkedTo(0).one
  1282.                         IF handle = LinkedTo(ii).one THEN SWAP MenuDisplayOrder(i, LinkedTo(ii).another), MenuDisplayOrder(i + gap, LinkedTo(ii).another)
  1283.                         IF handle = LinkedTo(ii).another THEN SWAP MenuDisplayOrder(i, LinkedTo(ii).one), MenuDisplayOrder(i + gap, LinkedTo(ii).one)
  1284.                     NEXT
  1285.                     swapped = -1
  1286.                 END IF
  1287.                 i = i + 1
  1288.             LOOP UNTIL i + gap > Menu(handle).Entries
  1289.         LOOP UNTIL gap = 1 AND swapped = 0
  1290.         IF sortmethod AND Reverse THEN
  1291.             FOR i = 1 TO Menu(handle).Entries \ 2
  1292.                 SWAP MenuDisplayOrder(i, handle), MenuDisplayOrder(Menu(handle).Entries - i + 1, handle)
  1293.                 FOR ii = 1 TO LinkedTo(0).one
  1294.                     IF handle = LinkedTo(ii).one THEN SWAP MenuDisplayOrder(i, LinkedTo(ii).another), MenuDisplayOrder(Menu(handle).Entries - i + 1, LinkedTo(ii).another)
  1295.                     IF handle = LinkedTo(ii).another THEN SWAP MenuDisplayOrder(i, LinkedTo(ii).one), MenuDisplayOrder(Menu(handle).Entries - i + 1, LinkedTo(ii).one)
  1296.                 NEXT
  1297.             NEXT
  1298.         END IF
  1299.     ELSE
  1300.         FOR i = 1 TO Menu(handle).Entries
  1301.             MenuDisplayOrder(i, handle) = i
  1302.             FOR ii = 1 TO LinkedTo(0).one
  1303.                 IF handle = LinkedTo(ii).one THEN MenuDisplayOrder(i, LinkedTo(ii).another) = i
  1304.                 IF handle = LinkedTo(ii).another THEN MenuDisplayOrder(i, LinkedTo(ii).one) = i
  1305.             NEXT
  1306.         NEXT
  1307.     END IF
  1308.  
  1309.  

(BI and BM files have been merged into the main module for ease of sharing).

The version of this demo included in SODR v0.5.7z (the dice roller zip file) won't run.  It was included simply by mistake, and was used only as a means for me to strip out the declarations and routines to create the LinkedList.BI and LinkedList.BM files which are needed for the dice roller to work.

Here is a version of the routine which showcases how the library works and performs for us.  We can easily create a list of things.  Link one list to another, if we want...  Sort them.  Select them.  Hide them...  Invalidate choices...  It's a very powerful little library, and one which I plug into a lot of little things for when I need a menu of choices. 

The lists scroll.  They're sortable.  The do all kinds of stuff!

And, once you toss the library into a program, it does all it does in a suprisingly short number of lines and commands -- here's the main routine of demo with the includes stripped out:

Code: QB64: [Select]
  1. 'Before here goes BI file content
  2. 'After here goes working program
  3.  
  4. DEFLNG A-Z
  5. SCREEN _NEWIMAGE(800, 600, 32)
  6.  
  7. MainMenu = GetMenuHandle
  8. SetMenuSize MainMenu, 200, 150
  9. SetMenuPosition MainMenu, 100, 100
  10. SetMenuFrame MainMenu, True, Red, Yellow
  11. SetMenuVisible MainMenu, True
  12. SetMenuCaption MainMenu, True, "Name", Black, White, True
  13. SetMenuListProperties MainMenu, Black, 0, Center 'Right 'Left
  14. SetMenuHighLightColor MainMenu, Red
  15. FOR i = 1 TO 23
  16.     READ n$
  17.     AddMenuItem MainMenu, n$
  18.  
  19. DATA Steve,Pete,Bob,Joe,Fred
  20. DATA Sam,One,Two,Three,Four
  21. DATA Five,Six,Seven,Eight,Nine
  22. DATA These,are,all,my,names
  23. DATA "Aren't",they,grand
  24.  
  25. SecondMenu = GetMenuHandle
  26. SetMenuSize SecondMenu, 100, 150
  27. SetMenuPosition SecondMenu, 300, 100
  28. SetMenuFrame SecondMenu, True, Red, Yellow
  29. SetMenuVisible SecondMenu, True
  30. SetMenuCaption SecondMenu, True, "Age", Black, White, True
  31. SetMenuListProperties SecondMenu, Black, 0, Left
  32. SetMenuHighLightColor SecondMenu, Red
  33.  
  34. FOR i = 1 TO 23
  35.     READ n$
  36.     AddMenuItem SecondMenu, n$
  37.  
  38. DATA 12,23,34,45,56
  39. DATA 67,78,89,90,1
  40. DATA 9,98,87,76,65
  41. DATA 54,43,32,21,10
  42. DATA 42,55,12
  43.  
  44. sortmode = 0: linked = -1: menuon = 1
  45.  
  46. HideMenuScrollBar MainMenu
  47. LinkMenus MainMenu, SecondMenu
  48.  
  49. DisableItem MainMenu, 5
  50. ScrollDelay = .25
  51.     CLS
  52.     LOCATE 20, 1: PRINT "Press <H> to hide the menu."
  53.     PRINT "Press <S> to show the menu."
  54.     PRINT "Press <N> for No Sort order."
  55.     PRINT "Press <A> for Alphabetic Sort order."
  56.     PRINT "Press <#> for Numeric Sort order."
  57.     PRINT "Press <C> to toggle case sorting."
  58.     PRINT "Press <R> to toggle reverse sorting."
  59.     PRINT "Press <L> to link the menus."
  60.     PRINT "Press <U> to unlink the menus."
  61.     PRINT "Press <TAB> to swap between menus."
  62.     PRINT "<ESC> to quit"
  63.     PRINT
  64.     PRINT "Currently: ";
  65.     IF sortmode AND 1 THEN
  66.         PRINT "ALPHA SORT";
  67.         IF kase THEN PRINT ", CASE-SENSITIVE";
  68.         IF reversed THEN PRINT ", REVERSE-ORDER" ELSE PRINT
  69.     ELSEIF sortmode AND 2 THEN
  70.         PRINT "NUMERIC SORT";
  71.         IF reversed THEN PRINT ", REVERSE-ORDER" ELSE PRINT
  72.     ELSE
  73.         PRINT "NOT SORTING"
  74.     END IF
  75.     LOCATE 5, 25
  76.     IF linked THEN PRINT "LINKED LISTS" ELSE PRINT "UNLINKED LISTS"
  77.     LOCATE 6, 15: PRINT "MENU ASSOCIATED WITH KEYBOARD: "; menuon
  78.  
  79.     MouseScroll = 0
  80.         MouseScroll = MouseScroll + _MOUSEWHEEL
  81.     WEND
  82.  
  83.     k = _KEYHIT
  84.     SELECT CASE k
  85.         CASE ASC("L"), ASC("l"): LinkMenus MainMenu, SecondMenu: linked = -1
  86.         CASE ASC("U"), ASC("u"): UnLinkMenus MainMenu, SecondMenu: linked = 0
  87.         CASE ASC("H"), ASC("h"): HideMenu menuon
  88.         CASE ASC("S"), ASC("s"): ShowMenu menuon
  89.         CASE ASC("N"), ASC("n"): sortmode = None: changed = -1: reversed = 0: kase = 0
  90.         CASE ASC("A"), ASC("a"): sortmode = Alpha: changed = -1
  91.         CASE ASC("#"), ASC("3"): sortmode = Numeric: changed = -1
  92.         CASE ASC("C"), ASC("c"): kase = NOT kase: changed = -1
  93.         CASE ASC("R"), ASC("r"): reversed = NOT reversed: changed = -1
  94.         CASE 9: menuon = menuon + 1: IF menuon = 3 THEN menuon = 1
  95.         CASE 27: SYSTEM
  96.     END SELECT
  97.     IF changed THEN
  98.         IF sortmode <> 0 THEN
  99.             IF kase THEN sortmode = sortmode OR NoCase ELSE sortmode = sortmode AND NOT NoCase
  100.             IF reversed THEN sortmode = sortmode OR Reverse ELSE sortmode = sortmode AND NOT Reverse
  101.         END IF
  102.         MenuDisplaySort menuon, sortmode
  103.         changed = 0
  104.     END IF
  105.     DisplayMenus
  106.     CheckMenus MouseStatus, MenuSelected, OptionSelected
  107.     IF MouseStatus <> 0 AND MenuSelected <> 0 THEN
  108.         IF MouseStatus AND LeftClick THEN
  109.             LOCATE 1, 1
  110.             PRINT "You LEFT CLICKED Option #"; OptionSelected; " in Menu #"; MenuSelected
  111.             PRINT "Which was: "; GetListItem(MenuSelected, OptionSelected)
  112.             PRINT
  113.             IF linked THEN
  114.                 PRINT "Since our lists are linked, we get the following items:"; GetListItem(1, OptionSelected), GetListItem(2, OptionSelected)
  115.             ELSE
  116.                 PRINT "Since our lists are unlinked, we get the following items:"; GetListItem(MenuSelected, OptionSelected)
  117.             END IF
  118.             _DISPLAY
  119.             _DELAY 2 'give it time to pop up
  120.         ELSEIF MouseStatus AND RightClick THEN
  121.             LOCATE 1, 1
  122.             PRINT "You RIGHT CLICKED Option #"; OptionSelected; " in Menu #"; MenuSelected
  123.             PRINT "Which was: "; GetListItem(MenuSelected, OptionSelected)
  124.             PRINT
  125.             IF linked THEN
  126.                 PRINT "Since our lists are linked, we get the following items:"; GetListItem(1, OptionSelected), GetListItem(2, OptionSelected)
  127.             ELSE
  128.                 PRINT "Since our lists are unlinked, we get the following items:"; GetListItem(MenuSelected, OptionSelected)
  129.             END IF
  130.             _DISPLAY
  131.             _DELAY 2 'give it time to pop up
  132.         END IF
  133.         COLOR Yellow
  134.         IF MouseStatus AND LeftDown THEN LOCATE 35, 1: PRINT "LEFT MOUSE DOWN over Option #"; OptionSelected; " in Menu #"; MenuSelected
  135.         IF MouseStatus AND RightDown THEN LOCATE 35, 1: PRINT "RIGHT MOUSE DOWN over Option #"; OptionSelected; " in Menu #"; MenuSelected
  136.         COLOR Purple
  137.         IF MouseStatus AND Hover THEN LOCATE 36, 1: PRINT "HOVERING over Option #"; OptionSelected; " in Menu #"; MenuSelected;
  138.         COLOR White
  139.  
  140.     END IF
  141.     _LIMIT 30
  142.     _DISPLAY
  143.  
  144. 'And here goes the BM routines

Less than 150 lines for the program to create the lists and interact with them as the demo illustrates, and it highlights a whole bunch of the options which one can make use of with the library.  Sorting.  Linking lists.  Unlinking lists.  Selecting things.  Hiding lists.  Restoring lists.  Scrolling via the mouse wheel or in-built sliders.  Hiding/showing sliders.  Making selections unavailable, and restoring availability... 

Lots of stuff going on in the little demo here, and in the end, it's all handled in very few lines once the library is '$INCLUDE with the program.  ;)
Title: Re: Linked Lists Demo
Post by: Pete on January 17, 2019, 10:56:05 am
Good work, only one error.

First DATA statement should read:

DATA Pete,Steve,Bob,Joe,Fred

Not

DATA Steve,Pete,Bob,Joe,Fred

Pete ;D
Title: Re: Linked Lists Demo
Post by: STxAxTIC on January 17, 2019, 12:03:27 pm
Looks like a handy utility, whether or not I split hairs on the definition of a linked list.
Title: Re: Linked Lists Demo
Post by: SMcNeill on January 17, 2019, 01:09:17 pm
Looks like a handy utility, whether or not I split hairs on the definition of a linked list.

In this case, the definition fits perfectly.  Make a list.  Then make a second one.  Then you “link” them together so what you do to one it does to the other....   Name, Age, Phone Number — 3 potentially different lists of things that we generally keep together.

If you sort the data by name, you’d normally want the Age and Phone Number to start in proper order with those names, so they’d sort as well...  Scroll down the list for one, it needs to scroll down all the other lists as well.  Invalidate one person from being selectable, his age and phone number shouldn’t be selectable either...

Those lists are “linked” so whatever action you take with one occurs with the others as well.  If those aren’t “linked lists”, what would you call them?  “Quantumly Entangled Lists”?  ;D
Title: Re: Linked Lists Demo
Post by: FellippeHeitor on January 17, 2019, 01:39:55 pm
Quote
If those aren’t “linked lists”, what would you call them?
Records in a database.

This is what STx (and general cs) mean by linked list: https://en.wikipedia.org/wiki/Linked_list
Title: Re: Linked Lists Demo
Post by: SMcNeill on January 17, 2019, 02:15:39 pm
Quote
If those aren’t “linked lists”, what would you call them?
Records in a database.

This is what STx (and general cs) mean by linked list: https://en.wikipedia.org/wiki/Linked_list

I understand Stx’s Definition of the term, but sometimes a term can be used to represent more than one concept.

“Bass” is a type of fish.
“Bass” is also a low pitch radio output.

“Records in a Database” doesn’t really fit, as these are 3 *different* datasets that we’re “linking” together to work with as one unit. 

We see it all the time in business application software...  one Dataset might be customer address and phone number.  Another dataset is customer payment method and account status.  Generally, those records are stored separately, in multiple databases, for security.  Close out one account, it should close the other “linked” record as well, but the databases are separate...

At its heart, QB64’s internal idet$ is a “linked list” such as you’re talking about, but what I’m talking about here is “linking two separate lists together to share the same behavioral properties”...

Maybe instead of “linked lists”, I should call this a “List Linking Library”....  But the question remains: What’s the simple term you’d call to explain the relationship between those two separate datasets which we “other word than link” together?
Title: Re: Linked Lists Demo
Post by: bplus on January 17, 2019, 02:23:56 pm
Quote
Maybe instead of “linked lists”, I should call this a “List Linking Library”....  But the question remains: What’s the simple term you’d call to explain the relationship between those two separate datasets which we “other word than link” together?

"Relational Database" but "List Linking Library" is less confusing than "Linked Lists" being used for your purpose.
https://www.google.com/search?client=opera&q=relational+database+model&sourceid=opera&ie=UTF-8&oe=UTF-8
Title: Re: Lists Linking Demo
Post by: SMcNeill on January 17, 2019, 02:34:31 pm
Quote
Maybe instead of “linked lists”, I should call this a “List Linking Library”....  But the question remains: What’s the simple term you’d call to explain the relationship between those two separate datasets which we “other word than link” together?

"Relational Database" but "List Linking Library" is less confusing than "Linked Lists" being used for your purpose.
https://www.google.com/search?client=opera&q=relational+database+model&sourceid=opera&ie=UTF-8&oe=UTF-8

Title changed.  Gosh, you guys are hard to please. 

It’s understandable why some folks refuse to share code anymore; folks get lost in arguing over the semantics of the terminology too much to actually talk about the code itself anymore.  No wonder most companies just refer to things as “Project 1X3RT7” and such...
Title: Re: Lists Linking Demo
Post by: Pete on January 17, 2019, 03:16:30 pm
Weren't you the guy who posted in another thread that you were hard to offend? Well, that wasn't hard.

I would have gone with... Remember guys, it's only all about nomenclature in an all female society.

Pete :D
Title: Re: Lists Linking Demo
Post by: SMcNeill on January 17, 2019, 03:32:48 pm
Weren't you the guy who posted in another thread that you were hard to offend? Well, that wasn't hard.

I would have gone with... Remember guys, it's only all about nomenclature in an all female society.

Pete :D

Didn’t say I was offended; just said I understood why others might choose not to bother with the hassle.  You’re getting as bad as the Democrats at reading things into a statement that isn’t there.  :P
Title: Re: Lists Linking Demo
Post by: Pete on January 17, 2019, 05:33:34 pm
Lucky for you, I'm not easily offended! Wait, did you compare me to a Democrat? Why you &^$$^%$c 6Z^%67%5^%z^ T^%8 ^5!!!!!

Pete :D
Title: Re: Lists Linking Demo
Post by: _vince on January 18, 2019, 06:25:51 pm
FYI, there's the database concept of linking tables, where two or more different tables are joined together with a separate table in a similar address linking fashion ;-)

Further reading: https://en.wikipedia.org/wiki/Associative_entity (https://en.wikipedia.org/wiki/Associative_entity)
Title: Re: Lists Linking Demo
Post by: SMcNeill on January 18, 2019, 06:53:20 pm
FYI, there's the database concept of linking tables, where two or more different tables are joined together with a separate table in a similar address linking fashion ;-)

No, no, no. 

You can’t use the word linking; it’s not acceptable. 

You have to say, “... concept of relationally databasing tables”, or “... in a similar address quantum entanglement fashion”.  That word “link” is too basic for BASIC, to be valid.

(And what you describe is exactly what the library does here: it creates an additional table/list behind the scenes to join two or more others together.)

And funnily enough: 

“Associative tables are colloquially known under many names, including association table, bridge table, cross-reference table, crosswalk, intermediary table, intersection table, join table, junction table, link table, linking table, many-to-many resolver, map table, mapping table, pairing table, pivot table (as used incorrectly in Laravel - not to be confused with the correct use of pivot table in spreadsheets), or transition table.”

And, of course, “list” is just another word for a “table”, so if we put those words together, it becomes the dreaded, “link list” or “linking list”...
Title: Re: Lists Linking Demo
Post by: STxAxTIC on January 19, 2019, 01:12:04 am
... more flailing casuistry. You just can't let it (me) go, can you? Just admit you're probably still not aware of what a real linked list is, and why some people react when you use those words together haphazardly, that's all. So simple.
Title: Re: Lists Linking Demo
Post by: SMcNeill on January 19, 2019, 02:51:22 am
... more flailing casuistry. You just can't let it (me) go, can you? Just admit you're probably still not aware of what a real linked list is, and why some people react when you use those words together haphazardly, that's all. So simple.

Go take a look in QB64.bas.  Idet$ is a basic linked list as you’re speaking of...

Now, go to Microsoft Access.  You’ll find a Linked Table Manager in there, which is basically a way of linking multiple tables together into one document.

And, let’s take a moment to look at what the dictionary offers us for “table”:

Quote
a set of facts or figures systematically displayed, especially in columns.
"the population has grown, as shown in table 1"

synonyms
list · chart · diagram · figure · graph · plan · catalog · inventory · digest · enumeration · tabulation · index · directory · register · itemization · record ·

Gee, what’s the very first synonym in that table of words??



But, you’re right: I don’t understand why some folks react like they do when those words are used together.  Most people I know understand that the same words can have very different meanings, and they’ll generally accept if they’re used in a manner different than they’re used to.

A set of data in a single column has always been a “list” to me.  A grocery list.  A to-do list.  A list of medications taken.

A set of data in multiple columns is usually referred to as being in a table.   Table of contents has both Chapter and Page Number found on the same line.

As this is a routine which “links” the behavior of two singular sets of data — “lists”.  I don’t think it’s the least bit wrong to call it a Linking Lists Library.  If the name’s unfitting, give me a better one. 

Should we call it “Records in a Database Library” as per Fell?  “Relational Database Library” as per bplus?  “The No Idea Library” as per Stx?

You don’t like what it’s called; give me something better and more descriptive to call it. 

Personally, in the Spirit of BASIC, I don’t see what could be a simpler name for it.  Take one list, then another list, and PRESTO — “link” them together.
Title: Re: Lists Linking Demo
Post by: FellippeHeitor on January 19, 2019, 05:47:56 am
What I probably didn't make clear when I first interacted with this thread is that I don't care what it's called.

Steve is in a funny (Clippy + [banned user]) mode in this thread and that's funny. That doesn't match you, man. Let it go.

(There comes a wall).
Title: Re: Lists Linking Demo
Post by: Pete on January 19, 2019, 11:33:18 am
Here's may take one the link lists from this thread:

Pete --- Thinks like a Democrat

Steve --- Thinks like Clippy

I'm pretty sure happenings like this were mentioned in some chapter of some well read book somewhere. Oh yeah, Revelations, form The Bible.

Well, it's like they say... It doesn't matter if you call it a mountain lion or  cougar, if you argue over that while it's stalking you, all it knows is your names are lunch.

Pete

Title: Re: Lists Linking Demo
Post by: STxAxTIC on January 19, 2019, 01:50:56 pm
I should apologize for my tone (I still might).

So first things first - my version of qb64.bas does not contain Idet$ for some reason. But that's irrelevant because a linked list is not just a string, either, so I can't imagine what point you make by directing me there. And the concept does not involve parallel tables or two arrays that need to point to each other. All of that is fluff, all of that misses the forest for the trees.

Let me try to fix things up here for our readers who didn't know...

An classical array is analogous to a pre-hollowed-out space in memory - a manifold if you like - into which you cram data. Even if you can change properties on the fly, such as the total number of elements, this is still a classical array. (Old news.) One assumption we make about storing data that way is the concept of "neighbors". On a rigid manifold, any given element has definite neighbors. You expect array member 4 to be sandwiched between members 3 and 5, so that when we loop through the elements, we hit 3, 4, 5 in order, all the way up to N or whatever. Again, all old news.

The classical array structure has plenty of problems, especially speed problems when the number of elements is large. To do any legwork in the array, we are often looping through the entire list of elements until landing on the right one - sortof like reading through the entire phonebook from the beginning until you find the entry you need... And god forbid you need to make an edit. For a classical array, we need to constantly bump existing elements to make room for the new elements. This is where naive text editors go wrong - if I want to make random edits near the top of a large file, the whole bulk of the text below needs to be jumping up and down the array at an amazing speed, and generates enough lag to kill the project, or to force wonky hacks. Even if computers *do* get fast enough to not notice the problems here, should we really be asking the machine to do all that extra work?

Proponents of linked lists say "no". To understand them is very simple. Throw away the idea of a classical array - the manifold - and thus the notion of "neighbors" goes out the window. There is no notion of jumbling data between bins anymore. To store one unit data in a linked list, you need (at bare minimum) three things:

1) The data itself, such as the letter "F", the number 7, or the whole encyclopedia (for the sake of argument).

2) An address to hold that data. This is just a unique integer that represents each element. Now check this out: In a classical array, these addresses go in linear order. The new idea is that in the linked list scheme, the linearity is not necessary. The data can occupy any unique address at all.

3) A pointing value holding the "next" element's address.

So one node in the list might be ("F",3,7), which stores the letter "F" at address 3, and then points to the next address at 7. This could mean there is some other node ("U",7,19) that stores the letter "U" at address 7, but then points out to 19, and so on. You can have more than one list in the same address space, you can have lists that intersect and merge like a half-zipped zipper or something... You may also violate linearity and create trees this way. Adding, removing, and rearranging elements becomes completely trivial with zero array shuffling.

So in conclusion, I'll admit, I didn't look closely at your code enough to decide if you're actually doing what I described here. If so, then congratulations, you may revert the thread title to what you had originally set.

Title: Re: Lists Linking Demo
Post by: SMcNeill on January 19, 2019, 02:42:18 pm
So first things first - my version of qb64.bas does not contain Idet$ for some reason. But that's irrelevant because a linked list is not just a string, either, so I can't imagine what point you make by directing me there. And the concept does not involve parallel tables or two arrays that need to point to each other. All of that is fluff, all of that misses the forest for the trees.

I more or less quit reading after this point, as you obviously have no clue of... pretty much anything.

idet$ is the variable where QB64 stores our code when we type it into the IDE.  It's found in numerous places inside the qb64 source, and if you can't locate it, you simply didn't bother to check the $INCLUDE files inside the source.

The way idet$ works is like this (from memory, feel free to check the source for specifics):

It stores a pointer for the length of a line + 8.
It stores the line.
It stores a pointer for the length of a line + 8.

So when reading this "list", the first pointer tells you how far to move to get to the data of the next line...

Now, see if that doesn't fill the definition of a "linked list" as you like to act oh-so-superior about:

Quote
In computer science, a Linked list is a linear collection of data elements, whose order is not given by their physical placement in memory. Instead, each element points to the next. It is a data structure consisting of a collection of nodes which together represent a sequence. In its most basic form, each node contains: data, and a reference (in other words, a link) to the next node in the sequence.

a Linked list is a linear collection of data elements --- Check, it's all in one line of data in the string.

each element points to the next -- Yep.  It does that.

It is a data structure consisting of a collection of nodes which together represent a sequence.  -- Yep.  It's the sequence of lines that you enter into the IDE which makes up your code.

In its most basic form, each node contains: data, and a reference (in other words, a link) to the next node in the sequence. -- Yep, that's what it is.

But that's irrelevant because a linked list is not just a string, either, so I can't imagine what point you make by directing me there.

Maybe you need to do a little research to figure out what exactly you're trying to talk about, before you decide to proclaim someone else wrong on the issue.



Edit: Here, a little bit of the code from QB64 for you to consider:
Code: QB64: [Select]
  1. a$ = MKL$(l& + LEN(a$)) + a$ + idet$ + MKL$(l& + LEN(a$)) 'header, data & encapsulation (reverse navigatable list)

Gee, what does that look like?
Title: Re: Lists Linking Demo
Post by: STxAxTIC on January 19, 2019, 02:51:49 pm
Would the nearest hack care to explain this screenshot then?

Is my QB64 version *that* old? The string ain't there bro. If so, then accuse me of being BASIC, haha.

Steve, listen to Fellippe - you need to let this whole thing go right after you concede the point, or go silent like you do on other threads where my argument lands against you. Don't accuse me of whatever hillbilly version of belittlement you detect, either. I'm being nothing but informative here.
Title: Re: Lists Linking Demo
Post by: FellippeHeitor on January 19, 2019, 02:54:40 pm
Idet$ is just a string you can find in ide_methods.bas. Not the exact definition of a linked list despite Steve advocating for it, but a clever hack Galleon came up to keep the whole loaded program in a structure other than an array (why? Beats me. But it works).

It differs from a linked list essentially because the elements are always in order.
Title: Re: Lists Linking Demo
Post by: STxAxTIC on January 19, 2019, 02:58:32 pm
Ah, thanks Fellippe. Sorry to imply you were a hack (but you DID answer first), haha...

But Steve would clearly contest your finding:
Quote
Go take a look in QB64.bas.  Idet$ is a basic linked list as you’re speaking of...

Wonder how he'll prove himself right *this* time...

Title: Re: Lists Linking Demo
Post by: SMcNeill on January 19, 2019, 03:12:33 pm
Idet$ is just a string you can find in ide_methods.bas. Not the exact definition of a linked list despite Steve advocating for it, but a clever hack Galleon came up to keep the whole loaded program in a structure other than an array (why? Beats me. But it works).

It differs from a linked list essentially because the elements are always in order.

It doesnt have to be, if Galleon would’ve updated the pointers...

Pointer of 100 + 8 ‘to move forward
100 characters of text
Pointer of 100 + 8 ‘to move backward
Pointer of 32 + 8 ‘to move forward
32 characters of text
Pointer of 32 + 8 ‘to move backwards


Now, say I want to add a line between the 100 characters and the 32...

Pointer of 132 + 24 ‘to move forward
100 characters of text
Pointer of 100 + 8 ‘backwards
Pointer of 32 + len(newline) + pointersizes
32 characters of text
Pointer of 8 ‘to move back, skip this pointer
Pointer of -40 ‘to move forward to next line
The new line of data
.....


The original was 1 points to 2...
The new is 1 points to the 3rd line entered, which then points to the second line entered...

Why Galleon chose to always keep idet$ in order is beyond me.  With the list structure, he didn’t have to do that.  As it is, I don’t see why a simple array wouldn’t have been more efficient...


Title: Re: Lists Linking Demo
Post by: SMcNeill on January 19, 2019, 03:13:56 pm
Wonder how he'll prove himself right *this* time...

By simply *being* right.  :P
Title: Re: Lists Linking Demo
Post by: SMcNeill on January 19, 2019, 03:17:40 pm
Would the nearest hack care to explain this screenshot then?

Is my QB64 version *that* old? The string ain't there bro. If so, then accuse me of being BASIC, haha.

Bro, can you read??

Quote
idet$ is the variable where QB64 stores our code when we type it into the IDE.  It's found in numerous places inside the qb64 source, and if you can't locate it, you simply didn't bother to check the $INCLUDE files inside the source.
Title: Re: Lists Linking Demo
Post by: STxAxTIC on January 19, 2019, 03:18:48 pm
Sigh, so according to you:

qb64.bas = ide_methods.bas

... I'm glad I don't listen to you, man. Let's just drop this.
Title: Re: Lists Linking Demo
Post by: SMcNeill on January 19, 2019, 03:21:37 pm
Sigh, so according to you:

qb64.bas = ide_methods.bas

... I'm glad I don't listen to you, man. Let's just drop this.

Try to delete ide_methods and see what happens when you compile. QB64.bas.  It’s an integral part of the source...

Just because it’s inside an $INCLUDE doesn’t mean it’s not there...
Title: Re: Lists Linking Demo
Post by: STxAxTIC on January 19, 2019, 03:23:49 pm
At this point I'm just playing with who gets the last word on this completely failed thread.
Title: Re: Lists Linking Demo
Post by: SMcNeill on January 19, 2019, 03:28:54 pm
At this point I'm just playing with who gets the last word on this completely failed thread.

Nice to see an internet troll admitting to their boorishness for a change.  Here, some advice for you:

Quote
...you need to let this whole thing go right after you concede the point, or go silent like you do on other threads where my argument lands against you. Don't accuse me of whatever hillbilly version of belittlement you detect, either. I'm being nothing but informative here.
Title: Re: Lists Linking Demo
Post by: STxAxTIC on January 19, 2019, 03:40:44 pm
Okay so let's recap.

You started this thread not knowing how to identify a linked list, and changed your mind on what to call this thread after several of us dropped hints.

Instead of conceding anything, you instead doubled down that you were right in the first place.

Then I throw down how it finally works, something a Wikidive could have told you.

You pretend not to read my explanation, and magically divine "aha, I can refer to an example of this that someone else made! (still not a real example)"

I'm not sure where your work enters this discussion.
Title: Re: Lists Linking Demo
Post by: SMcNeill on January 19, 2019, 04:00:43 pm
Okay so let's recap.

You started this thread not knowing how to identify a linked list, and changed your mind on what to call this thread after several of us dropped hints.

Instead of conceding anything, you instead doubled down that you were right in the first place.

Then I throw down how it finally works, something a Wikidive could have told you.

You pretend not to read my explanation, and magically divine "aha, I can refer to an example of this that someone else made! (still not a real example)"

I'm not sure where your work enters this discussion.

I was right in the first place. 

It’s just a shame that you can’t comprehend the idea that a name can be associated with different things.  You want to object to this being called a “linked list”, yet you can offer no insight as to what you think it should be called.  It’s a “linking table”, though since it deals primarily with a single column of data, I prefer the term “list” over “table” — and you’ve given no reason why “table/list” shouldn’t be interchangeable.

It’s also a shame that you don’t even know how an $INCLUDE file works, and can’t comprehend that idet$ *is* a linked list — it’s simply an optimized linked list, forced to be kept in order for some odd reason only known by Galleon.   Obviously you have no idea of the very “Linked Lists” you rant so heavily over— you can’t recognize one in its simplest form — nor do you have any comprehension of Linking Tables, yet you like to pretend to be all-knowing on the subject...

Do some research and learn a bit about the subjects you’re arguing over.  As it is, you just come across as a belligerent idiot to me.
Title: Re: Lists Linking Demo
Post by: Pete on January 19, 2019, 04:11:07 pm
From Bill's post, now a ways back because I took a nap...

Quote
Proponents of linked lists say "no".

But the problem here is that Ancient Alien Theorists say, "yes."

--------------------------

Yeah the word processing was a good example. I had an idea way back to do something like this...

Say we have 3 records...

1 Pete
2 Steve
3 Rick

Now we missed Bill, and want to insert him into space 1. Yes, with arrays, that would mean we'd have to reassign Pete to 2, Steve to 3 and Rick to 4. However, if we had a tracking string that increased each a record was added, we could just leave these arrays as... a$(1) = "Pete" a$(2) = "Steve" a$(3) = "Rick" and a$(4) = "Bill" So how do we get the order with that tracking string? Like so... tracking$ = "4|1|2|3" it's very easy to manipulate a tracking string with INSTR() and MID$(). So when we need to repront the screen, we consult the tracking string, parse it out and it reprints the order as 4,1,2,3. It also identifies the correct record by the line you are on. If you cursor to line 3...

1 Bill
2 Pete
-->    3 Steve
4 Rick

it looks at the third number in the tracking string, which is 2. This is the array "Steve" was assigned to.

Good stuff guys. Let's see if we can keep it up but without biting each other's heads off. You know we really need Clippy for that.

Pete
Title: Re: Lists Linking Demo
Post by: _vince on January 20, 2019, 05:07:24 am
I, too, have a qb64 linked lists example.  These are the proper "doubly linked lists" with the classic textbox/editor example along with storing a whole string per node.

@Steve, the term "linked list" is very specific and well known term in the programming/CS community, like the terms "binary tree", "pointer", "data type", "stack space", "variable", and so on, as it is a specific technique for a particular problem with shuffling items in a list as described by stx.  It is not interchangeable with "linking table" as I've jokingly pointed out, so it's pretty misleading to use the it for something else, that is all.  It would be like calling badminton "basketball" because the ball is basket shaped, logical only if "basketball" wasn't the already established term that it is.

Code: QB64: [Select]
  1. defint a-z
  2.  
  3. type nodeType
  4.         str as _mem
  5.         strLen as integer
  6.  
  7. 'you can add more data to store per node here
  8.  
  9.         n as _mem
  10.         p as _mem
  11.  
  12. type listType
  13.         head as _mem
  14.         tail as _mem
  15.  
  16.  
  17. dim new as listType
  18. dim cur as _mem
  19. dim temp as _mem
  20.  
  21. newList new
  22.  
  23. 'insert garbage
  24. addNodeNext temp, "test1", new.head
  25. addNodeNext temp, "test2", temp
  26. addNodeNext temp, "test3", temp
  27. addNodeNext temp, "test4", temp
  28. addNodePrev temp, "testa", new.tail
  29. addNodePrev temp, "estb", temp
  30. addNodePrev temp, "", temp
  31. addNodePrev temp, "td", temp
  32.  
  33. printList new
  34.  
  35. nextNode cur, new.head
  36.  
  37. cx = 1
  38. cy = 1
  39.  
  40.         cls
  41.         locate 1,1
  42.         printList new
  43.  
  44.         locate cy,cx
  45.         color 0,7
  46.         print chr$(screen(cy,cx))
  47.         color 7,0
  48.  
  49.         do
  50.                 k$ = inkey$
  51.         loop until len(k$)>0
  52.  
  53.         select case k$
  54.         case chr$(13) 'enter
  55.                 if cy = 1 and cx = 1 then
  56.                         addNodePrev cur, "", cur
  57.                 elseif -1 then
  58.                         s$ = readNode$(cur)
  59.                         ss$ = right$(s$, len(s$)-cx+1)
  60.                         s$ = left$(s$, cx-1)
  61.                         writeNode cur, s$
  62.                         addNodeNext cur, ss$, cur
  63.                         cy = cy + 1
  64.                         cx = 1
  65.                 end if
  66.  
  67.         case chr$(8) 'backspace
  68.                 if cx = 1 then
  69.                         if cy > 1 then
  70.                                 s$ = readNode$(cur)
  71.                                 temp = cur
  72.                                 prevNode cur, cur
  73.                                 ss$ = readNode$(cur)
  74.                                 cx = len(ss$) + 1
  75.                                 writeNode cur, ss$ + s$
  76.                                 cy = cy-1
  77.                                 rmNode temp
  78.                         end if
  79.                 elseif cx > 1 then
  80.                         cx = cx - 1
  81.                         s$ = readNode$(cur)
  82.                         ss$ = left$(s$, cx-1) + right$(s$, len(s$)-cx)
  83.                         writeNode cur, ss$
  84.                 end if
  85.  
  86.         case chr$(0)+"K" 'left
  87.                 if cx > 1 then cx = cx - 1
  88.  
  89.         case chr$(0)+"M" 'right
  90.                 s$ = readNode$(cur)
  91.                 if cx <= len(s$) then cx = cx + 1
  92.  
  93.         case chr$(0)+"H" 'up
  94.                 s$ = readNode$(cur)
  95.                 if cy > 1 then
  96.                         prevNode cur, cur
  97.                         s$ = readNode$(cur)
  98.                         if cx > len(s$) then cx = len(s$) + 1
  99.                         cy = cy - 1
  100.                 end if
  101.  
  102.         case chr$(0)+"P" 'down
  103.                 nextNode temp, cur
  104.                 if temp.offset <> new.tail.offset then
  105.                         cur = temp
  106.                         s$ = readNode$(cur)
  107.                         if cx > len(s$) then cx = len(s$) + 1
  108.                         cy = cy + 1
  109.                 end if
  110.  
  111.         case chr$(32) to chr$(128)
  112.                 s$ = readNode$(cur)
  113.                 s$ = mid$(s$,1,cx-1) + k$ + right$(s$, len(s$)-cx+1)
  114.                 writeNode cur, s$
  115.                 cx = cx + 1
  116.         end select
  117.  
  118. loop until k$ = chr$(27)
  119.  
  120. sub addNodeNext (new as _mem, s$, cur as _mem)
  121.         dim node as nodeType
  122.         dim temp as _mem
  123.         dim n as _mem
  124.  
  125.         temp = _memnew(len(node))
  126.  
  127.         nextNode n, cur
  128.  
  129.         node.strLen = len(s$)
  130.         if node.strLen > 0 then
  131.                 node.str = _memnew(len(s$))
  132.                 _memput node.str, node.str.offset, s$
  133.         end if
  134.         node.n = n
  135.         node.p = cur
  136.         _memput temp, temp.offset, node
  137.  
  138.         node = _memget(cur, cur.offset, nodeType)
  139.         node.n = temp
  140.         _memput cur, cur.offset, node
  141.  
  142.         node = _memget(n, n.offset, nodeType)
  143.         node.p = temp
  144.         _memput n, n.offset, node
  145.  
  146.         new = temp
  147.  
  148. sub addNodePrev (new as _mem, s$, cur as _mem)
  149.         dim node as nodeType
  150.         dim temp as _mem
  151.         dim p as _mem
  152.  
  153.         temp = _memnew(len(node))
  154.  
  155.         prevNode p, cur
  156.  
  157.         node.strLen = len(s$)
  158.         if node.strLen > 0 then
  159.                 node.str = _memnew(len(s$))
  160.                 _memput node.str, node.str.offset, s$
  161.         end if
  162.  
  163.         node.n = cur
  164.         node.p = p
  165.         _memput temp, temp.offset, node
  166.  
  167.         node = _memget(cur, cur.offset, nodeType)
  168.         node.p = temp
  169.         _memput cur, cur.offset, node
  170.  
  171.         node = _memget(p, p.offset, nodeType)
  172.         node.n = temp
  173.         _memput p, p.offset, node
  174.  
  175.         new = temp
  176.  
  177. sub rmNode (cur as _mem)
  178.         dim node as nodeType
  179.         dim n as _mem
  180.         dim p as _mem
  181.  
  182.         'remove the string first
  183.         node = _memget(cur, cur.offset, nodeType)
  184.         if node.strLen > 0 then
  185.                 _memfree node.str
  186.         end if
  187.  
  188.         nextNode n, cur
  189.         prevNode p, cur
  190.  
  191.         node = _memget(p, p.offset, nodeType)
  192.         node.n = n
  193.         _memput p, p.offset, node
  194.  
  195.         node = _memget(n, n.offset, nodeType)
  196.         node.p = p
  197.         _memput n, n.offset, node
  198.  
  199.         _memfree cur
  200.  
  201. sub nextNode (new as _mem, old as _mem)
  202.         dim node as nodeType
  203.  
  204.         node = _memget(old, old.offset, nodeType)
  205.         new = node.n
  206.  
  207. sub prevNode (new as _mem, old as _mem)
  208.         dim node as nodeType
  209.  
  210.         node = _memget(old, old.offset, nodeType)
  211.         new = node.p
  212.  
  213. function readNode$ (cur as _mem)
  214.         dim node as nodeType
  215.  
  216.         node = _memget(cur, cur.offset, nodeType)
  217.         if node.strLen = 0 then
  218.                 readNode$ = ""
  219.                 exit function
  220.         end if
  221.         s$ = string$(node.strLen, 0)
  222.         _memget node.str, node.str.offset, s$
  223.  
  224.         readNode$ = s$
  225.  
  226. sub writeNode (cur as _mem, s$)
  227.         dim node as nodeType
  228.  
  229.         'remove old string, freeing memory
  230.         node = _memget(cur, cur.offset, nodeType)
  231.         if node.strLen > 0 then _memfree node.str
  232.  
  233.         'add new string
  234.         node.strLen = len(s$)
  235.         if node.strLen > 0 then
  236.                 node.str = _memnew(len(s$))
  237.                 _memput node.str, node.str.offset, s$
  238.         end if
  239.         _memput cur, cur.offset, node
  240.  
  241. sub newList (new as listType)
  242.         dim node as nodeType
  243.  
  244.         new.head = _memnew(len(node))
  245.         new.tail = _memnew(len(node))
  246.  
  247.         s$ = "head"
  248.         node.strLen = len(s$)
  249.         node.str = _memnew(len(s$))
  250.         node.n = new.tail
  251.         node.p = new.tail
  252.         _memput node.str, node.str.offset, s$
  253.         _memput new.head, new.head.offset, node
  254.  
  255.         s$ = "tail"
  256.         node.strLen = len(s$)
  257.         node.str = _memnew(len(s$))
  258.         node.n = new.head
  259.         node.p = new.head
  260.         _memput node.str, node.str.offset, s$
  261.         _memput new.tail, new.tail.offset, node
  262.  
  263. sub printList (cur as listType)
  264.         dim temp as _mem
  265.  
  266.         nextNode temp, cur.head
  267.         do
  268.                 if temp.offset = cur.tail.offset then exit do
  269.  
  270.                 print readNode$ (temp)
  271.                 nextNode temp, temp
  272.         loop
  273.  
  274. sub rmList (cur as listType)
  275.         dim temp as _mem
  276.         dim temp2 as _mem
  277.  
  278.         nextNode temp, cur.head
  279.         do
  280.                 if temp.offset = cur.tail.offset then exit do
  281.  
  282.                 temp2 = temp
  283.                 nextNode temp, temp2
  284.                 rmNode temp2
  285.         loop
  286.  
  287.         rmNode cur.head
  288.         rmNode cur.tail
  289.  
  290.  
Title: Re: Lists Linking Demo
Post by: Pete on January 20, 2019, 11:01:44 am
Thanks for "pointing" out the C connection, V.

I read about that too, but I know next to nothing about the language, so I didn't want to chime in like I was some kind of authority. What I should have posted is from my limited reading, it appeared to me that the C language uses pointers and coined that phrase, "linked list" in association with putting data in nodes, which I assume are user determined memory locations. I would suspect people in that community would be more sensitive to how that term is defined when using other languages, especially ones like BASIC, which are not associated with using pointers. So the phrase, "What's in a name?" Well, maybe it is all up to who feels they have the most ownership of it. Something similar to this happened to me this morning when I was looking through Bing news and clicked on a headline about PGA Awards. I was expecting a golf article, but instead got some crap about "Producers Guild Awards."

Anyway, QB64 has the C _MEM keywords that bridge the gap into linked lists. I've haven't used those QB64 keywords yet, so thanks V, for posting a node example. It will take me awhile to get to it but hopefully not to long to absorb it. I have always had to rely on the technique I described in the last post or the rather elaborate use of arrays, which I believe that article I read stated was the next best way to link data in a non-pointer language.

Pete
Title: Re: Lists Linking Demo
Post by: SMcNeill on January 20, 2019, 11:32:47 am
Quote
It would be like calling badminton "basketball" because the ball is basket shaped, logical only if "basketball" wasn't the already established term that it is.

Maybe it’s just a regional thing; as I know us hillbillies have our own lingo, but the term I’m using is perfectly suitable around here, just as some places seem to call “soccer” as “football”, even though it’s obviously something different.  I’ve never said a Linked List wasn’t used as you illustrate; I’ve just said it’s also had a different meaning as I’ve known it.  Sometimes “football” is an oval shaped ball you throw in the air, sometimes it’s a circular ball hit with your head — yet, people are generally tolerant enough not to say, “Gee, you’re using that term wrong.”, or at least they’re willing to accept when told, “Well, that’s what we call the game here.”

Like I’ve mentioned, I’m more than willing to call the demo here by another name, if someone can suggest something better to describe what it’s doing.  My biggest problem with folks complaining over the name is simply nobody has actually offered a suggestion of what it should be called. 

I’m thinking of renaming it the  “FIN GUT.BM LIBRARY — Fuck It, Nobody Gets to Use This, But Me LIBRARY.”  If somebody ever wants to do something similar, let them do it themselves and call it whatever the hell they want.
Title: Re: Lists Linking Demo
Post by: Pete on January 20, 2019, 12:48:14 pm
I tried your new name but I got a "Duplicate Definition" error when I tried to run it.

Pete :D
Title: Re: Lists Linking Demo
Post by: TempodiBasic on January 20, 2019, 05:39:31 pm
Pete
What name do you search, in specific?
:-)

following your explanation about linked lists
Quote
Say we have 3 records...

1 Pete
2 Steve
3 Rick

now if we add the forth record "Bill"
in the original list we add at the end the new record...
Original List          Desired List
1 Pete                 1 Bill
2 Steve               2 Pete
3 Rick                 3 Steve
4 Bill                   4 Rick

stored in new variable  tracking$ = "4|1|2|3" --> that is the index of Desired List
now we can order in increasing alphabetical   AlphaIncrease$ = "4|1|3|2"
and we can order in decreasing alphabetical  AlphaDecrese$ = "2|3|1|4"
and we can extract names including "i"  NameI$ = "4|3"
and we can extract names including  two "e"  NameE$="1|2"
the thing becomes interesting....
Title: Re: Lists Linking Demo
Post by: Pete on January 20, 2019, 09:24:09 pm
Since you showed some interest in this method, I'll post some working code. It's pretty limited, but it will demonstrate how a tracking string would work...

T$ is the tracking string.
r is the record number in sequential order of entry.

Code: QB64: [Select]
  1. separator$ = "|"
  2. LOCATE , , 1, 7, 7
  3.     _LIMIT 30
  4.     b$ = INKEY$
  5.     IF b$ <> "" THEN
  6.         yy% = CSRLIN
  7.         SELECT CASE b$
  8.             CASE CHR$(0) + "H"
  9.                 IF CSRLIN > 1 THEN LOCATE CSRLIN - 1
  10.             CASE CHR$(0) + "P"
  11.                 IF CSRLIN < 4 THEN LOCATE CSRLIN + 1
  12.             CASE "A" TO "z", "0" TO "9"
  13.                 IF a$(yy%) = "" AND r < 4 THEN
  14.                     PRINT b$;
  15.                     GOSUB text
  16.                 ELSE
  17.                     BEEP ' For this demo, overwrite is not allowed. Only insert.
  18.                 END IF
  19.             CASE CHR$(0) + "R" ' Insert Key
  20.                 IF r < 8 THEN ' Allow up to 8 lines with insert, 4 with just enter.
  21.                     ' Move all entries one line down the screen.
  22.                     PRINT SPACE$(80)
  23.                     GOSUB getseed
  24.                     DO
  25.                         x$ = MID$(t$, seed%, INSTR(seed%, t$, separator$) - seed% + 1) ' Include separator to insure names are unique when concatenated.
  26.                         PRINT SPACE$(80);
  27.                         LOCATE , 1
  28.                         PRINT a$(VAL(x$))
  29.                         seed% = seed% + LEN(x$)
  30.                     LOOP UNTIL seed% > LEN(t$)
  31.                     LOCATE yy%, 1
  32.                     b$ = ""
  33.                     GOSUB text
  34.                 ELSE
  35.                     BEEP ' Only allow 5 entries for this demo
  36.                 END IF
  37.             CASE CHR$(9)
  38.                 CLS
  39.                 seed% = 1
  40.                 FOR i = 1 TO r
  41.                     _DELAY .25
  42.                     x$ = MID$(t$, seed%, INSTR(seed%, t$, separator$) - seed% + 1)
  43.                     PRINT a$(VAL(x$))
  44.                     seed% = seed% + LEN(x$)
  45.                 NEXT
  46.                 yy% = CSRLIN
  47.                 LOCATE 20, 1: PRINT t$
  48.                 LOCATE yy%
  49.             CASE CHR$(27)
  50.                 SYSTEM
  51.         END SELECT
  52.     END IF
  53.  
  54. getseed:
  55. k% = 1: seed% = 1
  56. FOR i% = 1 TO LEN(t$)
  57.     IF k% = yy% THEN EXIT FOR
  58.     IF MID$(t$, i%, 1) = separator$ THEN k% = k% + 1
  59. seed% = i%
  60.  
  61. text:
  62. LOCATE yy%, 1
  63. r = r + 1
  64. a$(r) = b$ + x$
  65. GOSUB getseed
  66. insert$ = separator$
  67. t$ = MID$(insert$ + t$, 1, INSTR(seed%, insert$ + t$, separator$)) + LTRIM$(STR$(r)) + separator$ + MID$(insert$ + t$, INSTR(seed%, insert$ + t$, separator$) + 1)
  68. IF insert$ <> "" THEN t$ = MID$(t$, 2): insert$ = ""
  69. LOCATE 20, 1: PRINT "Tracking String = "; t$
  70. LOCATE yy% + 1, 1 ' Move next line down

Keys are type something and press ENTER. Works with Line Input function.
Insert something with INSERT key then type as usual. Stuff on screen under insert line will move down.
Use the TAB key to clear the screen and it wil print the order correctly, using the tracking string to decide the proper order.

Pete
Title: Re: Lists Linking Demo
Post by: _vince on January 21, 2019, 09:27:43 am
Thanks for "pointing" out the C connection, V.

I read about that too, but I know next to nothing about the language, so I didn't want to chime in like I was some kind of authority. What I should have posted is from my limited reading, it appeared to me that the C language uses pointers and coined that phrase, "linked list" in association with putting data in nodes, which I assume are user determined memory locations. I would suspect people in that community would be more sensitive to how that term is defined when using other languages, especially ones like BASIC, which are not associated with using pointers. So the phrase, "What's in a name?" Well, maybe it is all up to who feels they have the most ownership of it. Something similar to this happened to me this morning when I was looking through Bing news and clicked on a headline about PGA Awards. I was expecting a golf article, but instead got some crap about "Producers Guild Awards."

Anyway, QB64 has the C _MEM keywords that bridge the gap into linked lists. I've haven't used those QB64 keywords yet, so thanks V, for posting a node example. It will take me awhile to get to it but hopefully not to long to absorb it. I have always had to rely on the technique I described in the last post or the rather elaborate use of arrays, which I believe that article I read stated was the next best way to link data in a non-pointer language.

Pete

Nothing to do with C specifically, I have not mentioned C, these are general concepts applicable to all languages. _MEM is not a C keyword but a QB64 keyword.

QBasic/QB45 has pointers as well, they exist within the realm controlled by statements such as PEEK, POKE, VARPTR (variable pointer), VARSEG (variable segment), SADD (string address), VARPTR$, DEF SEG, and so on.

I am going to add a few entries related to _MEM to my QB64/FB dictionary.
Title: Re: Lists Linking Demo
Post by: STxAxTIC on January 22, 2019, 08:08:07 am
Looks like we institutionally forgot that I made a full-blown doubly linked list text editor in QB64 a few months ago - the qXed project. I halted the effort to make it a cheap emacs clone because the quality of my internet connection forbids me to test certain online features... however that's irrelevant for this. Like Vince said, a "real" one would use one entire string per node. This one uses one character per node for... certain reasons I can explain. Literally too much to talk about with this program, so I've stripped a few things down to show the basics here.

So HERE is a working example of a doubly-linked list in action. It's a fully-working text editor, but the learning curve is a little steep, and I haven't explained a damn thing so you will think it's full of bugs unless you discover simple stuff.
Code: QB64: [Select]
  1. '$EXEICON:'qXedlogo.ico'
  2. '$RESIZE:ON
  3.  
  4. 'REM $Include: 'sxmath.bi'
  5. 'REM $Include: 'sxript.bi'
  6.  
  7. scrHand& = _NEWIMAGE(90, 30, 0)
  8. SCREEN scrHand&
  9. '_FREEIMAGE scrHand&
  10.  
  11. ' Define fundamental structures.
  12. TYPE Vector
  13.     X AS INTEGER
  14.     Y AS INTEGER
  15.  
  16. TYPE Cell
  17.     Identity AS LONG
  18.     Pointer AS LONG
  19.     Lagger AS LONG
  20.     Content AS STRING * 1
  21.  
  22. DIM SHARED ChainLimit AS LONG
  23. DIM SHARED BOC AS LONG ' Beginning of chain.
  24. DIM SHARED EOC AS LONG ' End of chain.
  25. ChainLimit = 128000
  26. BOC = -1
  27. EOC = ChainLimit
  28.  
  29. ' Define text window properties.
  30. DIM SHARED WindowHeight
  31. DIM SHARED WindowWidth
  32. DIM SHARED VisibleLines
  33. DIM SHARED TopIndent
  34. DIM SHARED LeftIndent
  35. DIM SHARED TextHeight
  36. DIM SHARED TextWidth
  37. DIM SHARED HScroll
  38. DIM SHARED TextWrapping
  39. DIM SHARED TextFormatting
  40. DIM SHARED InsertKey
  41. TopIndent = 1
  42. LeftIndent = 1
  43. WindowWidth = _WIDTH '
  44. WindowHeight = _HEIGHT '- 2
  45. TextHeight = WindowHeight - 2 * TopIndent
  46. TextWidth = WindowWidth - 2 * LeftIndent
  47. HScroll = 1
  48. TextWrapping = 0
  49. TextFormatting = -1
  50. InsertKey = -1
  51.  
  52. ' Initiate text inside window.
  53. DIM SHARED StartIndex
  54. DIM SHARED LineAsMapped(TextHeight) AS STRING
  55. DIM SHARED Cursor1 AS Vector
  56. DIM SHARED Cursor2 AS Vector
  57.  
  58. ' Auxiliary 2D text grid.
  59. DIM SHARED GOLSwitch
  60. DIM SHARED AuxGrid(TextWidth, TextHeight, 2) AS STRING
  61. GOLSwitch = -1
  62.  
  63. ' Load text file into memory if applicable, use example string if not.
  64. DIM SHARED FileName$
  65. IF (c$ <> "") THEN
  66.     q$ = ""
  67.     OPEN c$ FOR INPUT AS #1
  68.     DO WHILE NOT EOF(1)
  69.         LINE INPUT #1, r$
  70.         q$ = q$ + r$ + CHR$(13)
  71.     LOOP
  72.     CLOSE #1
  73.     i = INSTR(c$, ".")
  74.     IF (i <> 0) THEN j = i - 1 ELSE j = LEN(c$)
  75.     FileName$ = LEFT$(c$, j) + "-" + LTRIM$(RTRIM$(STR$(INT(TIMER)))) + ".txt"
  76.     _TITLE FileName$
  77.     FileName$ = "Newfile" + "-" + DATE$ + "-" + LTRIM$(RTRIM$(STR$(INT(TIMER)))) + ".txt"
  78.     q$ = "I sank to the floor. I [experienced] this hallucination of tumbling forward into these fractal geometric spaces made of light and then I found myself in the equivalent of the Pope's private chapel and there were insect elf machines proffering strange little tablets with strange writing on them, and I was aghast, completely appalled, because [in] a matter of seconds . . . my entire expectation of the nature of the world was just being shredded in front of me. I've never actually gotten over it. These self-transforming machine elf creatures were speaking in a colored language which condensed into rotating machines that were like Faberge eggs but crafted out of luminescent superconducting ceramics and liquid crystal gels. All this stuff was just so weird and so alien and so un-English-able that it was a complete shock - I mean, the literal turning inside out of [my] intellectual universe!" + CHR$(13) + CHR$(13) + "This went on for two or three minutes, this situation of [discontinuous] orthogonal dimensions to reality just engulfing me. As I came out of it and the room reassembled itself, I said, " + CHR$(34) + "I can't believe it, it's impossible." + CHR$(34) + " To call that a drug is ridiculous; that just means that you just don't have a word for it and so you putter around and you come upon this sloppy concept [that] something goes into your body and there's a change. It's not like that; it's like being struck by noetic lightning. [Note: " + CHR$(34) + "Noetic" + CHR$(34) + " derives from the theologian Pierre Teilhard de Chardin's " + CHR$(34) + "noosphere" + CHR$(34) + " - the collective consciousness of humankind conceived of as a sort of philosophical virtuality.]" + CHR$(13) + CHR$(13) + "[What] astonished me was [that] . . . in the carpets of Central Asia, in the myths of the Maya, in the visions of an Arcimboldi or a Fra Angelico or a Bosch, there is not a hint, not a clue, not an atom of the presence of this thing, This was more [multiplex] than the universe that we share with each other. It was the victory of Neo-Platonic metaphysics; everything [was] made out of a fourth-dimensional mosaic of energy. I was knocked off my feet, and set myself the goal of understanding this. There was really no choice, you see."
  79.     'q$ = " "
  80.  
  81. _TITLE "qXed"
  82.  
  83. ' Create memory space for string.                                      a
  84. DIM SHARED TheChain(ChainLimit) AS Cell
  85.  
  86. ' Create character list.
  87. CALL Assimilate(q$)
  88.  
  89. ' Prime main loop.
  90. CALL MapText
  91. CALL CalibrateCursor(ID1)
  92. CALL CalibrateCursor(ID2)
  93. CALL PrintEverything
  94.  
  95. DIM SHARED DEBUG$
  96.  
  97. ' Main loop.
  98.     IF (StateChange = 1) THEN
  99.         CALL PrintEverything
  100.     END IF
  101.  
  102.     IF (GOLSwitch = 1) THEN
  103.         CALL ConvertToGrid
  104.         CALL GOL
  105.         CALL ConvertFromGrid
  106.         CALL MapText
  107.         CALL PrintEverything
  108.     END IF
  109.  
  110.     'IF _RESIZE = -1 THEN
  111.     '    _DELAY .1
  112.     '    oldimage& = scrHand&
  113.     '    scrHand& = _NEWIMAGE(_RESIZEWIDTH / 8, _RESIZEHEIGHT / 16, 0)
  114.     '    SCREEN scrHand&
  115.     '    _FREEIMAGE oldimage&
  116.     '    WindowWidth = INT(_RESIZEWIDTH / 8)
  117.     '    WindowHeight = INT(_RESIZEHEIGHT / 16)
  118.     '    TextHeight = WindowHeight - 2 * TopIndent
  119.     '    TextWidth = WindowWidth - 2 * LeftIndent
  120.     '    REDIM LineAsMapped(TextHeight)
  121.     '    REDIM AuxGrid(TextWidth, TextHeight, 2)
  122.     '    CALL MapText
  123.     '    CALL CalibrateCursor(ID1)
  124.     '    CALL CalibrateCursor(ID2)
  125.     '    CALL PrintEverything
  126.     'END IF
  127.  
  128.     _DISPLAY
  129.     _LIMIT 120
  130.  
  131. SUB PrintEverything
  132.     CLS
  133.  
  134.     c$ = "qXed" + " " + DEBUG$
  135.     CALL DisplayText(1, 1, 11, 0, c$)
  136.  
  137.     ' Main text
  138.     FOR i = 1 TO VisibleLines
  139.         c$ = LineAsMapped(i)
  140.         IF ((TextFormatting = 1) AND (TextWrapping <> 2)) THEN
  141.             FOR j = 1 TO TextWidth - LEN(c$)
  142.                 c$ = c$ + "_"
  143.             NEXT
  144.         END IF
  145.         d$ = MID$(c$, HScroll, TextWidth)
  146.         CALL DisplayText(LeftIndent + 1, TopIndent + i, 7, 1, d$)
  147.     NEXT
  148.  
  149.     ' Cursor2
  150.     IF ((Cursor2.X > 0 AND Cursor2.X < WindowWidth) AND ((Cursor2.Y > 0) AND (Cursor2.Y < WindowHeight))) THEN
  151.         p1 = LinearCount(StartIndex, ID1)
  152.         p2 = LinearCount(StartIndex, ID2)
  153.         pe = LinearCount(StartIndex, EOC)
  154.         IF ((p2 > p1) AND (p2 < pe)) THEN
  155.             c$ = TheChain(ID2).Content
  156.             IF (c$ = " ") THEN c$ = "_"
  157.             IF (c$ = CHR$(13)) THEN c$ = "~"
  158.             CALL DisplayText(Cursor2.X, Cursor2.Y, 0, 6, c$)
  159.         END IF
  160.     END IF
  161.  
  162.     ' Cursor1
  163.     IF ((Cursor1.X > 0 AND Cursor1.X < WindowWidth) AND ((Cursor1.Y > 0) AND (Cursor1.Y < WindowHeight))) THEN
  164.         c$ = TheChain(ID1).Content
  165.         IF (c$ = " ") THEN c$ = "_"
  166.         IF (c$ = CHR$(13)) THEN c$ = "~"
  167.         IF ((Cursor1.X = Cursor2.X) AND (Cursor1.Y = Cursor2.Y)) THEN
  168.             a = 16: b = 5
  169.         ELSE
  170.             a = 16: b = 3
  171.         END IF
  172.         CALL DisplayText(Cursor1.X, Cursor1.Y, a, b, c$)
  173.     END IF
  174.  
  175.     ' Cursor status
  176.     d$ = TheChain(ID1).Content
  177.     e$ = TheChain(ID2).Content
  178.     IF ((ASC(d$) = 10) OR (ASC(d$) = 13)) THEN d$ = "~"
  179.     IF ((ASC(e$) = 10) OR (ASC(e$) = 13)) THEN e$ = "~"
  180.     IF (ASC(d$) = 32) THEN d$ = "_"
  181.     IF (ASC(e$) = 32) THEN e$ = "_"
  182.     c$ = "(" + LTRIM$(RTRIM$(STR$(Cursor1.X - LeftIndent))) + "," + LTRIM$(RTRIM$(STR$(Cursor1.Y - TopIndent))) + ":" + " " + LTRIM$(RTRIM$(d$)) + " " + LTRIM$(RTRIM$(STR$(ID1))) + ")"
  183.     a = 0: b = 3
  184.     IF ((Cursor1.X = Cursor2.X) AND (Cursor1.Y = Cursor2.Y)) THEN
  185.         a = 15: b = 5
  186.     END IF
  187.     CALL DisplayText(2, WindowHeight, a, b, c$)
  188.     g$ = "(" + LTRIM$(RTRIM$(STR$(Cursor2.X - LeftIndent))) + "," + LTRIM$(RTRIM$(STR$(Cursor2.Y - TopIndent))) + ":" + " " + LTRIM$(RTRIM$(e$)) + " " + LTRIM$(RTRIM$(STR$(ID2))) + ")"
  189.     a = 6: b = 0
  190.     IF (LinearCount(StartIndex, ID2) > LinearCount(StartIndex, ID1)) THEN
  191.         a = 0: b = 6
  192.     END IF
  193.     CALL DisplayText(3 + LEN(c$), WindowHeight, a, b, g$)
  194.     ' Horizontal scrollbar
  195.     p = LinearCount(NthP(StartIndex, FindID(LeftIndent + 1, Cursor1.Y)), ID1)
  196.     q = LEN(LineAsMapped(Cursor1.Y - TopIndent))
  197.     r = p / q
  198.     IF r > 1 THEN r = 1
  199.     IF r < 0 THEN r = 0
  200.     i = 2 + INT(r * (WindowWidth - 2))
  201.     IF i < 1 THEN i = 1
  202.     IF i > WindowWidth THEN i = WindowWidth
  203.     CALL DisplayText(i, WindowHeight - 1, 8, 7, "^")
  204.  
  205.     ' Vertical scrollbar
  206.     p = LinearCount(ID1, NthP(ID1, ChainLimit + 1))
  207.     q = LinearCount(NthL(ID1, ChainLimit + 1), NthP(ID1, ChainLimit + 1))
  208.     IF (q = 0) THEN r = 1 ELSE r = 1 - p / q
  209.     CALL DisplayText(WindowWidth, 1 + INT(r * (WindowHeight - 1)), 8, 7, "<")
  210.  
  211.     ' Help
  212.     SELECT CASE TextWrapping
  213.         CASE 0: d$ = "Square"
  214.         CASE 1: d$ = "Fluid"
  215.         CASE 2: d$ = "None"
  216.     END SELECT
  217.     c$ = "[F6=Save] [F11=Format] [F12=Wrap: " + d$ + "]"
  218.     IF (TextWrapping = 2) THEN c$ = "[F1/2=HScroll] " + c$
  219.     c$ = c$ + STR$(INT(100 * r)) + "%"
  220.     IF (LEN(c$) >= TextWidth) THEN c$ = LEFT$(c$, TextWidth)
  221.     CALL DisplayText(WindowWidth - LEN(c$), 1, 15, 0, c$)
  222.     c$ = "[Esc=Sync] [Mouse2=Copy] [Mouse3=Paste]"
  223.     IF (InsertKey = 1) THEN c$ = "[Ins] " + c$
  224.     IF (LEN(c$) >= TextWidth) THEN c$ = LEFT$(c$, TextWidth)
  225.     CALL DisplayText(WindowWidth - LEN(c$), WindowHeight, 15, 0, c$)
  226.  
  227.     ' Pointer
  228.     IF ((_MOUSEX >= 1) AND (_MOUSEX <= WindowWidth) AND (_MOUSEY >= 1) AND (_MOUSEY <= WindowHeight)) THEN
  229.         a$ = CHR$(SCREEN(_MOUSEY, _MOUSEX))
  230.         CALL DisplayText(_MOUSEX, _MOUSEY, 0, 15, a$)
  231.     END IF
  232.  
  233.     COLOR 15, 0
  234.  
  235.  
  236. SUB Assimilate (a AS STRING)
  237.     ' Load a string to initialize chain.
  238.     FOR k = 1 TO ChainLimit
  239.         TheChain(k).Identity = 0
  240.     NEXT
  241.     StartIndex = 1
  242.     PreviousIdentity = BOC
  243.     NextIdentity = NextOpenIdentity(StartIndex)
  244.     FOR k = 1 TO LEN(a)
  245.         j = NextIdentity
  246.         TheChain(j).Identity = j
  247.         TheChain(j).Content = ReFormat$(MID$(a, k, 1))
  248.         TheChain(j).Lagger = PreviousIdentity
  249.         PreviousIdentity = j
  250.         IF (k < LEN(a)) THEN
  251.             NextIdentity = NextOpenIdentity(j)
  252.             TheChain(j).Pointer = NextIdentity
  253.         ELSE
  254.             TheChain(j).Pointer = EOC
  255.         END IF
  256.         PRINT TheChain(j).Content
  257.     NEXT
  258.     ID1 = StartIndex
  259.     ID2 = NthP(ID1, ChainLimit + 1)
  260.  
  261. FUNCTION ReFormat$ (a AS STRING)
  262.     c$ = a
  263.     IF c$ = CHR$(10) THEN c$ = CHR$(13)
  264.     IF c$ = CHR$(9) THEN c$ = "    "
  265.     ReFormat = c$
  266.  
  267. FUNCTION NthP (a AS LONG, b AS LONG)
  268.     ' Returns the address that is b jumps ahead of address a.
  269.     i = a
  270.     IF (i <> EOC) THEN
  271.         k = 0
  272.         j = 0
  273.         DO WHILE (k < b)
  274.             k = k + 1
  275.             j = TheChain(i).Identity
  276.             i = TheChain(j).Pointer
  277.             IF (i = EOC) THEN EXIT DO
  278.         LOOP
  279.     END IF
  280.     NthP = j
  281.  
  282. FUNCTION NthPC (a AS LONG, b AS STRING)
  283.     ' Returns the address holding b first enLinearCountered from a.
  284.     i = a
  285.     DO
  286.         j = TheChain(i).Identity
  287.         i = TheChain(j).Pointer
  288.         IF (TheChain(j).Content = b) THEN EXIT DO
  289.         IF (i = EOC) THEN
  290.             j = BOC
  291.             EXIT DO
  292.         END IF
  293.     LOOP
  294.     NthPC = j
  295.  
  296. FUNCTION NthL (a AS LONG, b AS LONG)
  297.     ' Returns the address that is b jumps behind address a.
  298.     i = a
  299.     k = 0
  300.     DO WHILE k < b
  301.         k = k + 1
  302.         j = TheChain(i).Identity
  303.         i = TheChain(j).Lagger
  304.         IF (i = BOC) THEN EXIT DO
  305.     LOOP
  306.     NthL = j
  307.  
  308. FUNCTION NextOpenIdentity (a AS LONG)
  309.     ' Returns first nonzero identity.
  310.     FOR j = a TO ChainLimit
  311.         IF (TheChain(j).Identity = 0) THEN EXIT FOR
  312.     NEXT
  313.     IF (j > ChainLimit) THEN
  314.         PRINT "Out of memory: "; ChainLimit
  315.         SLEEP
  316.         SYSTEM
  317.     END IF
  318.     NextOpenIdentity = j
  319.  
  320. FUNCTION BackBreak (a AS LONG)
  321.     ' Function for scrolling up.
  322.     j = a
  323.     lastbreak = 0
  324.     c$ = ""
  325.     DO
  326.         IF (j = BOC) THEN EXIT DO
  327.         k = TheChain(j).Lagger
  328.         IF (k = BOC) THEN
  329.             lastbreak = j
  330.             EXIT DO
  331.         END IF
  332.         j = k
  333.         d$ = TheChain(j).Content
  334.         IF ((TextWrapping = 1) AND (d$ = " ")) THEN lastbreak = j
  335.         c$ = d$ + c$
  336.         IF (TextWrapping <> 2) AND (LEN(c$) = TextWidth) THEN EXIT DO
  337.         IF (d$ = CHR$(13)) THEN EXIT DO
  338.     LOOP
  339.     IF (lastbreak <> 0) THEN j = TheChain(lastbreak).Identity
  340.     BackBreak = j
  341.  
  342. SUB InsertBefore (a AS LONG, b AS STRING)
  343.     ' Inserts a single cell before address a in the chain.
  344.     j = NextOpenIdentity(a)
  345.     al = TheChain(a).Lagger
  346.     TheChain(j).Identity = j
  347.     TheChain(j).Pointer = a
  348.     TheChain(j).Lagger = al
  349.     TheChain(j).Content = ReFormat$(b)
  350.     TheChain(a).Lagger = j
  351.     IF (al = BOC) THEN StartIndex = j ELSE TheChain(al).Pointer = j
  352.  
  353. SUB InsertAfter (a AS LONG, b AS STRING)
  354.     ' Inserts a single cell after address a in the chain.
  355.     j = NextOpenIdentity(a)
  356.     ap = TheChain(a).Pointer
  357.     TheChain(j).Identity = j
  358.     TheChain(j).Pointer = ap
  359.     TheChain(j).Lagger = a
  360.     TheChain(j).Content = ReFormat$(b)
  361.     TheChain(a).Pointer = j
  362.     IF (ap <> EOC) THEN TheChain(ap).Lagger = j
  363.  
  364. SUB InsertRange (a AS LONG, b AS STRING)
  365.     ' Inserts a sub-chain anywhere.
  366.     FOR k = 1 TO LEN(b)
  367.         c$ = MID$(b, k, 1)
  368.         CALL InsertBefore(a, c$)
  369.     NEXT
  370.  
  371. SUB UnlinkCell (a AS LONG)
  372.     ' Remove single cell from chain and clear identity.
  373.     ap = TheChain(a).Pointer
  374.     al = TheChain(a).Lagger
  375.     IF ((ap = EOC) AND (al = BOC)) THEN
  376.         TheChain(a).Content = " "
  377.         'ID1 = a
  378.         'ID2 = ID1
  379.     ELSE
  380.         TheChain(a).Identity = 0
  381.         IF ((ap <> EOC) AND (al <> BOC)) THEN
  382.             TheChain(al).Pointer = ap
  383.             TheChain(ap).Lagger = al
  384.         END IF
  385.         IF (ap = EOC) THEN TheChain(al).Pointer = EOC
  386.         IF (al = BOC) THEN
  387.             StartIndex = ap
  388.             TheChain(ap).Lagger = BOC
  389.         END IF
  390.     END IF
  391.  
  392. SUB UnlinkRange (a AS LONG, b AS LONG)
  393.     ' Remove sub-chain and clear identity of each cell.
  394.     bp = TheChain(b).Pointer
  395.     al = TheChain(a).Lagger
  396.     IF ((al = BOC) AND (bp = EOC)) THEN
  397.         CALL UnlinkRange(NthP(a, 2), b)
  398.         TheChain(a).Content = " "
  399.         TheChain(a).Pointer = bp
  400.     ELSE
  401.         k = a
  402.         DO WHILE ((k <> b) AND (k <> EOC))
  403.             TheChain(k).Identity = 0
  404.             k = TheChain(k).Pointer
  405.         LOOP
  406.         TheChain(b).Identity = 0
  407.         TheChain(bp).Lagger = al
  408.         IF (al = BOC) THEN StartIndex = bp ELSE TheChain(al).Pointer = bp
  409.     END IF
  410.  
  411. FUNCTION LinearCount (a AS LONG, b AS LONG)
  412.     ' Returns number of links between two addresses.
  413.     i = a
  414.     k = 0
  415.     DO WHILE (i <> b)
  416.         k = k + 1
  417.         j = TheChain(i).Identity
  418.         i = TheChain(j).Pointer
  419.         IF (i = EOC) THEN EXIT DO
  420.     LOOP
  421.     LinearCount = k
  422.  
  423. FUNCTION LinearCount2 (a AS LONG, b AS LONG, c AS LONG)
  424.     ' Returns number of links between two addresses, with exit condition.
  425.     i = a
  426.     k = 0
  427.     DO WHILE (i <> b)
  428.         k = k + 1
  429.         j = TheChain(i).Identity
  430.         i = TheChain(j).Pointer
  431.         IF (i = EOC) THEN EXIT DO
  432.         IF (k = c) THEN EXIT DO
  433.     LOOP
  434.     LinearCount2 = k
  435.  
  436. FUNCTION Projection$ (a AS LONG, b AS LONG)
  437.     ' Returns the linear content for all address between a and b, inclusive.
  438.     DIM TheReturn AS STRING
  439.     TheReturn = ""
  440.     IF (a = b) THEN
  441.         TheReturn = TheChain(a).Content
  442.     ELSE
  443.         j = a
  444.         DO
  445.             c$ = TheChain(j).Content
  446.             TheReturn = TheReturn + c$
  447.             k = TheChain(j).Pointer
  448.             IF (j = b) THEN EXIT DO
  449.             IF (k = EOC) THEN EXIT DO
  450.             j = k
  451.         LOOP
  452.     END IF
  453.     Projection$ = TheReturn
  454.  
  455. SUB MapText
  456.     IF (TextFormatting = 1) THEN br$ = "~" ELSE br$ = " "
  457.     j = StartIndex
  458.     i = 1
  459.     q$ = ""
  460.     d$ = ""
  461.     DO ' Begin with any left-over text from previous iteration.
  462.         q$ = d$
  463.         d$ = ""
  464.         r = TextWidth - LEN(q$)
  465.         IF (TextWrapping <> 2) THEN k1 = NthP(j, r) ELSE k1 = EOC
  466.         k2 = NthPC(j, CHR$(13))
  467.         IF (TextWrapping <> 2) THEN c1 = LinearCount(j, k1) ELSE c1 = LinearCount2(j, k1, TextWidth * TextHeight)
  468.         c2 = LinearCount(j, k2)
  469.         IF (c2 = 0) THEN ' Line is blank-returned.
  470.             k = k2
  471.             q$ = q$ + br$
  472.             j = NthP(k, 2)
  473.         ELSE
  474.             IF (c1 = c2) THEN ' Possible end of chain.
  475.                 k = TheChain(k1).Lagger
  476.                 q$ = q$ + Projection$(j, k)
  477.                 j = NthP(k, 2)
  478.             END IF
  479.             IF (c1 < c2) THEN ' Width limit case (not always maximum).
  480.                 k = k1
  481.                 q$ = q$ + Projection$(j, k)
  482.                 j = NthP(k, 2)
  483.             END IF
  484.             IF (c1 > c2) THEN ' Break return somewhere in line (not first).
  485.                 k = k2
  486.                 q$ = q$ + Projection$(j, TheChain(k).Lagger) + br$
  487.                 n = TheChain(k).Pointer
  488.                 IF (n <> EOC) THEN j = n
  489.             END IF
  490.         END IF
  491.         IF (TextWrapping = 1) THEN ' Wrap text at first space from right, send remainder to next line.
  492.             IF (LEN(q$) >= TextWidth) THEN
  493.                 FOR m = LEN(q$) TO 1 STEP -1
  494.                     c$ = MID$(q$, m, 1)
  495.                     IF (c$ = " ") OR (c$ = "-") THEN
  496.                         q$ = LEFT$(q$, m)
  497.                         EXIT FOR
  498.                     END IF
  499.                     d$ = c$ + d$
  500.                     IF (m = 1) THEN ' Line is too long for allowed space and contains no wrapping characters.
  501.                         q$ = LEFT$(q$, TextWidth)
  502.                         d$ = ""
  503.                         EXIT FOR
  504.                     END IF
  505.                 NEXT
  506.             END IF
  507.         END IF
  508.         LineAsMapped(i) = q$
  509.         i = i + 1
  510.         IF (i >= TextHeight) THEN EXIT DO
  511.         IF (j = k) THEN EXIT DO
  512.     LOOP
  513.     VisibleLines = i - 1
  514.  
  515. FUNCTION StateChange
  516.     DIM TheReturn
  517.     MH = 0
  518.     MW = 0
  519.     MT = 0
  520.         MH1 = _MOUSEBUTTON(1)
  521.         MH2 = _MOUSEBUTTON(2)
  522.         MH3 = _MOUSEBUTTON(3)
  523.         MW = _MOUSEWHEEL
  524.         IF (MW <> 0) THEN MT = MW
  525.     LOOP
  526.     MW = MT
  527.  
  528.     IF (MH1 = -1) THEN
  529.         ' Move Cursor1 among text.
  530.         MH = 1
  531.         IF ((_MOUSEX > LeftIndent) AND (_MOUSEX < TextWidth + LeftIndent + 1) AND (_MOUSEY > TopIndent) AND (_MOUSEY < TopIndent + TextHeight)) THEN
  532.             Cursor1.X = _MOUSEX
  533.             q = LeftIndent + LEN(LineAsMapped(_MOUSEY - TopIndent))
  534.             IF (Cursor1.X > q) THEN Cursor1.X = q
  535.             Cursor1.Y = _MOUSEY
  536.             CALL ReassignID1
  537.         END IF
  538.         ' Move by vertical scrollbar.
  539.         IF (_MOUSEX = WindowWidth) THEN
  540.             i = NthL(ID1, ChainLimit + 1)
  541.             j = NthP(ID1, ChainLimit + 1)
  542.             IF (_MOUSEY = WindowHeight) THEN i = j
  543.             IF (_MOUSEY > 1) AND (_MOUSEY < WindowHeight) THEN
  544.                 t = LinearCount(i, j)
  545.                 f = _MOUSEY / WindowHeight
  546.                 FOR k = 1 TO t
  547.                     IF (k / t >= f) THEN EXIT FOR
  548.                     i = TheChain(i).Pointer
  549.                 NEXT
  550.             END IF
  551.             StartIndex = i
  552.             ID1 = i
  553.         END IF
  554.         ' Move by horizontal scrollbar.
  555.         IF (_MOUSEY = WindowHeight - 1) THEN
  556.             j = ID1
  557.             i = NthP(StartIndex, FindID(LeftIndent + 1, Cursor1.Y))
  558.             'IF (_MOUSEX = windowwidth - 1) THEN i = NthP(StartIndex, FindID(LeftIndent + LEN(LineAsMapped(Cursor1.Y - TopIndent)), Cursor1.Y) + (HScroll - 1))
  559.             IF (_MOUSEX > 1) AND (_MOUSEX < WindowWidth) THEN
  560.                 t = LEN(LineAsMapped(Cursor1.Y - TopIndent))
  561.                 f = _MOUSEX / WindowWidth
  562.                 FOR k = 1 TO t
  563.                     IF (k / t >= f) THEN EXIT FOR
  564.                     i = TheChain(i).Pointer
  565.                 NEXT
  566.             END IF
  567.             ID1 = i
  568.             d = LinearCount(StartIndex, i) - LinearCount(StartIndex, j)
  569.             IF (TextWrapping = 2) THEN HScroll = HScroll + d
  570.             IF HScroll < 1 THEN HScroll = 1
  571.         END IF
  572.     END IF
  573.     IF (MH2 = -1) THEN
  574.         ' Move Cursor2 and copy anything between Cursor1 and Cursor2 to clipboard.
  575.         MH = 1
  576.         IF (_MOUSEX > LeftIndent) AND (_MOUSEX < TextWidth + LeftIndent + 1) AND (_MOUSEY > TopIndent) AND (_MOUSEY < TopIndent + TextHeight + 1) THEN
  577.             Cursor2.X = _MOUSEX
  578.             q = LeftIndent + LEN(LineAsMapped(_MOUSEY - TopIndent))
  579.             IF (Cursor2.X > q) THEN Cursor2.X = q
  580.             Cursor2.Y = _MOUSEY
  581.             CALL ReassignID2
  582.             IF (LinearCount(StartIndex, ID2) > LinearCount(StartIndex, ID1)) THEN _CLIPBOARD$ = Projection$(ID1, ID2)
  583.         END IF
  584.     END IF
  585.     IF (MH3 = -1) THEN
  586.         ' Paste at Cursor1 position.
  587.         MH = 1
  588.         'IF (LinearCount(StartIndex, ID2) >= LinearCount(StartIndex, ID1)) THEN
  589.         CALL InsertRange(ID1, _CLIPBOARD$)
  590.     END IF
  591.     IF (MW = -1) THEN
  592.         ' Wheel up
  593.         MH = 1
  594.         StartIndex = BackBreak(StartIndex)
  595.         CALL ReassignID1
  596.     END IF
  597.     IF (MW = 1) THEN
  598.         ' Wheel down
  599.         MH = 1
  600.         IF (VisibleLines > 1) THEN
  601.             StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  602.             CALL MapText
  603.         END IF
  604.         CALL ReassignID1
  605.     END IF
  606.  
  607.     KH = 0
  608.     '''k$ = ""
  609.     '''k$ = INKEY$
  610.     '''IF k$ <> "" THEN KH = ASC(k$)
  611.     KH = _KEYHIT
  612.  
  613.     ' Bksp
  614.     IF (KH = 8) THEN
  615.         r = TheChain(ID1).Pointer
  616.         q = TheChain(ID1).Lagger
  617.         CALL UnlinkCell(ID1)
  618.         IF ((r = EOC) AND (q = BOC)) THEN
  619.         ELSE
  620.             IF (q <> BOC) THEN ID1 = q ELSE ID1 = r
  621.             IF (r = EOC) THEN ID2 = ID1
  622.         END IF
  623.     END IF
  624.     ' Tab
  625.     IF (KH = 9) THEN CALL InsertRange(ID1, "    ")
  626.     ' Esc
  627.     IF (KH = 27) THEN
  628.         IF (ID2 <> ID1) THEN ID2 = ID1 ELSE ID2 = StartIndex 'NthL(ID2, 2)
  629.     END IF
  630.     ' Enter, Alphanumerics
  631.     IF (KH = 13) OR ((KH >= 32) AND (KH <= 126)) THEN
  632.         IF (InsertKey = -1) THEN
  633.             IF (ID1 = ID2) THEN
  634.                 CALL InsertBefore(ID1, LTRIM$(RTRIM$(CHR$(KH))))
  635.             ELSE
  636.                 CALL InsertAfter(ID1, LTRIM$(RTRIM$(CHR$(KH))))
  637.                 ID1 = NthP(ID1, 2)
  638.             END IF
  639.         ELSE
  640.             TheChain(ID1).Content = LTRIM$(RTRIM$(CHR$(KH)))
  641.             IF (ID1 = ID2) THEN
  642.                 ID1 = NthP(ID1, 2)
  643.                 ID2 = ID1
  644.             ELSE
  645.                 ID1 = NthP(ID1, 2)
  646.             END IF
  647.         END IF
  648.         IF ((TextWrapping = 2) AND (Cursor1.X - LeftIndent = TextWidth)) THEN HScroll = HScroll + 1
  649.     END IF
  650.     ' F1
  651.     IF (KH = 15104) THEN
  652.         IF (TextWrapping = 2) THEN
  653.             HScroll = HScroll - 1
  654.             IF (HScroll < 1) THEN HScroll = 1
  655.             CALL ReassignID1
  656.             CALL ReassignID2
  657.         END IF
  658.     END IF
  659.     ' F2
  660.     IF (KH = 15360) THEN
  661.         IF (TextWrapping = 2) THEN
  662.             HScroll = HScroll + 1
  663.             CALL ReassignID1
  664.             CALL ReassignID2
  665.         END IF
  666.     END IF
  667.     ' F5
  668.     IF (KH = 16128) THEN
  669.         q$ = Projection$(NthL(ID1, ChainLimit + 1), NthP(ID1, ChainLimit + 1))
  670.         Assimilate q$
  671.     END IF
  672.     ' F4
  673.     'IF (KH = 15872) THEN
  674.     'CALL InsertRange(NthP(ID2, 2), CHR$(10) + "=" + CoreProcess$(Projection(ID1, ID2)))
  675.     'CALL InsertRange(NthP(ID2, 2), CHR$(10) + "=" + SxriptEval$(Projection(ID1, ID2)))
  676.     'ID2 = StartIndex
  677.     'END IF
  678.     ' F6
  679.     IF (KH = 16384) THEN
  680.         OPEN FileName$ FOR OUTPUT AS #1
  681.         q$ = Projection$(NthL(ID1, ChainLimit + 1), NthP(ID1, ChainLimit + 1))
  682.         PRINT #1, q$
  683.         CLOSE #1
  684.     END IF
  685.     ' F7
  686.     IF (KH = 16640) THEN
  687.         GOLSwitch = -GOLSwitch
  688.     END IF
  689.     ' F8 IF (KH = 16896) THEN
  690.     ' Home
  691.     IF (KH = 18176) THEN
  692.         IF (TextWrapping = 2) THEN HScroll = 1
  693.         Cursor1.X = LeftIndent + 1
  694.         CALL ReassignID1
  695.     END IF
  696.     ' UpArrow
  697.     IF (KH = 18432) THEN
  698.         IF (Cursor1.Y > TopIndent + 1) THEN
  699.             Cursor1.Y = Cursor1.Y - 1
  700.         ELSE
  701.             StartIndex = BackBreak(StartIndex)
  702.         END IF
  703.         q = LEN(LineAsMapped(Cursor1.Y - TopIndent)) + 1
  704.         IF (Cursor1.X > q) THEN Cursor1.X = q
  705.         CALL ReassignID1
  706.     END IF
  707.     ' PgUp
  708.     IF (KH = 18688) THEN
  709.         FOR k = 1 TO INT(TextHeight / 2)
  710.             StartIndex = BackBreak(StartIndex)
  711.         NEXT
  712.         CALL ReassignID1
  713.     END IF
  714.     ' LeftArrow
  715.     IF (KH = 19200) THEN
  716.         ID1 = NthL(ID1, 2)
  717.         IF (TextWrapping = 2) THEN
  718.             IF (Cursor1.X = LeftIndent + 1) THEN
  719.                 IF (HScroll > 1) THEN
  720.                     HScroll = HScroll - 1
  721.                 ELSE
  722.                     j = Cursor1.Y - TopIndent - 1
  723.                     IF (j >= 1) THEN
  724.                         k = LEN(LineAsMapped(j)) - TextWidth + 1
  725.                         IF (k >= 1) THEN
  726.                             HScroll = k
  727.                         END IF
  728.                     END IF
  729.                 END IF
  730.             END IF
  731.         ELSE
  732.             IF ((Cursor1.X - LeftIndent = 1) AND Cursor1.Y - TopIndent = 1) THEN
  733.                 StartIndex = BackBreak(StartIndex)
  734.             END IF
  735.         END IF
  736.     END IF
  737.     ' RightArrow
  738.     IF (KH = 19712) THEN
  739.         ID1 = NthP(ID1, 2)
  740.         m = Cursor1.X - LeftIndent
  741.         n = LEN(LineAsMapped(Cursor1.Y - TopIndent)) - HScroll + 1
  742.         IF (TextWrapping = 2) THEN
  743.             IF (m >= TextWidth) THEN
  744.                 HScroll = HScroll + 1
  745.                 CALL ReassignID1
  746.             END IF
  747.             IF (m >= n) THEN
  748.                 j = Cursor1.Y - TopIndent + 1
  749.                 IF ((j <= TextHeight) AND (VisibleLines > 1)) THEN HScroll = 1
  750.             END IF
  751.         ELSE
  752.             IF ((m >= n) AND (Cursor1.Y - TopIndent = VisibleLines)) THEN
  753.                 IF (VisibleLines > 1) THEN StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  754.             END IF
  755.         END IF
  756.     END IF
  757.     ' End
  758.     IF (KH = 20224) THEN
  759.         Cursor1.X = LeftIndent + LEN(LineAsMapped(Cursor1.Y - TopIndent))
  760.         CALL ReassignID1
  761.         IF (TextWrapping = 2) THEN
  762.             q = LEN(LineAsMapped(Cursor1.Y - TopIndent)) - TextWidth + 1
  763.             IF (q >= 1) THEN HScroll = q
  764.         END IF
  765.     END IF
  766.     ' DownArrow
  767.     IF (KH = 20480) THEN
  768.         IF (Cursor1.Y = TopIndent + VisibleLines) THEN
  769.             IF (VisibleLines > 1) THEN
  770.                 StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  771.                 CALL MapText
  772.             END IF
  773.         ELSE
  774.             Cursor1.Y = Cursor1.Y + 1
  775.         END IF
  776.         q = LEN(LineAsMapped(Cursor1.Y - TopIndent)) + 1
  777.         IF (Cursor1.X > q) THEN
  778.             Cursor1.X = q
  779.         END IF
  780.         CALL ReassignID1
  781.     END IF
  782.     ' PgDn
  783.     IF (KH = 20736) THEN
  784.         FOR k = 1 TO INT(TextHeight / 2)
  785.             IF (VisibleLines > 1) THEN
  786.                 StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  787.                 CALL MapText
  788.             END IF
  789.         NEXT
  790.         CALL ReassignID1
  791.     END IF
  792.     ' Insert
  793.     IF (KH = 20992) THEN
  794.         InsertKey = -InsertKey
  795.     END IF
  796.     ' Del
  797.     IF (KH = 21248) THEN
  798.         IF (LinearCount(StartIndex, ID2) > LinearCount(StartIndex, ID1)) THEN
  799.             r = TheChain(ID2).Pointer
  800.             q = TheChain(ID1).Lagger
  801.             p = ID1
  802.             CALL UnlinkRange(ID1, ID2)
  803.             IF ((r = EOC) AND (q = BOC)) THEN
  804.                 ID1 = p
  805.                 ID2 = ID1
  806.                 StartIndex = p
  807.             ELSE
  808.                 IF (q <> BOC) THEN ID1 = q ELSE ID1 = r
  809.                 ID2 = NthP(ID1, 2)
  810.             END IF
  811.         END IF
  812.     END IF
  813.     ' F11
  814.     IF (KH = 34048) THEN TextFormatting = -TextFormatting
  815.     ' F12
  816.     IF (KH = 34304) THEN
  817.         TextWrapping = TextWrapping + 1
  818.         IF (TextWrapping > 2) THEN TextWrapping = 0
  819.         ID1 = StartIndex
  820.         ID2 = ID1
  821.         HScroll = 1
  822.     END IF
  823.     ' Exit sequence
  824.     TheReturn = 0
  825.     IF ((MH <> 0) OR (KH > 0)) THEN
  826.         TheReturn = 1
  827.         CALL MapText
  828.         CALL CalibrateCursor(ID1)
  829.         CALL CalibrateCursor(ID2)
  830.         ' Cursor sync and autoscrolling.
  831.         IF (Cursor1.Y > TopIndent + TextHeight - 1) THEN StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  832.     END IF
  833.     _KEYCLEAR
  834.     StateChange = TheReturn
  835.  
  836. SUB CalibrateCursor (a AS LONG)
  837.     ' Place Cursor under ID on rendered line.
  838.     s = StartIndex
  839.     IF ((TextWrapping = 2) AND (HScroll > 1)) THEN s = NthP(s, HScroll)
  840.     c = LinearCount(s, a)
  841.     k = 0
  842.     i = -1
  843.     FOR j = 1 TO VisibleLines
  844.         n = LEN(LineAsMapped(j))
  845.         IF (k + n < c) THEN
  846.             k = k + n
  847.         ELSE
  848.             i = c - k + 1
  849.             EXIT FOR
  850.         END IF
  851.     NEXT
  852.     IF (i >= LeftIndent + LEN(LineAsMapped(j))) THEN
  853.         IF (j <= VisibleLines) THEN
  854.             i = 1
  855.             j = j + 1
  856.         END IF
  857.     END IF
  858.     IF (a = ID1) THEN
  859.         Cursor1.X = LeftIndent + i
  860.         Cursor1.Y = TopIndent + j
  861.     END IF
  862.     IF (a = ID2) THEN
  863.         Cursor2.X = LeftIndent + i
  864.         Cursor2.Y = TopIndent + j
  865.     END IF
  866.  
  867. FUNCTION FindID (a AS INTEGER, b AS LONG)
  868.     ' Find identity under a map location.
  869.     RelX = a - LeftIndent
  870.     RelY = b - TopIndent
  871.     FOR k = 1 TO RelY - 1
  872.         t = t + LEN(LineAsMapped(k))
  873.     NEXT
  874.     t = t + RelX
  875.     FindID = t
  876.  
  877. SUB ReassignID1
  878.     ' Reassign identity under Cursor1.
  879.     ID1 = NthP(StartIndex, FindID(Cursor1.X, Cursor1.Y) + (HScroll - 1))
  880.  
  881. SUB ReassignID2
  882.     ' Reassign identity under Cursor2.
  883.     ID2 = NthP(StartIndex, FindID(Cursor2.X, Cursor2.Y) + (HScroll - 1))
  884.  
  885. SUB ConvertToGrid
  886.     FOR j = 1 TO VisibleLines
  887.         c$ = LineAsMapped(j)
  888.         FOR i = 1 TO LEN(c$) - 1 ' BR offset to exclude break return at line end.
  889.             AuxGrid(i, j, 1) = MID$(c$, i, 1)
  890.         NEXT
  891.     NEXT
  892.  
  893. SUB ConvertFromGrid
  894.     q$ = ""
  895.     FOR j = 1 TO VisibleLines
  896.         FOR i = 1 TO LEN(LineAsMapped(j)) - 1
  897.             q$ = q$ + AuxGrid(i, j, 1)
  898.         NEXT
  899.         q$ = q$ + CHR$(13) ' Undoes BR offset.
  900.     NEXT
  901.     Assimilate q$
  902.  
  903. SUB GOL
  904.     FOR j = 1 TO VisibleLines
  905.         FOR i = 1 TO LEN(LineAsMapped(j)) - 1
  906.             c$ = AuxGrid(i, j, 1)
  907.             IF (c$ = " ") THEN c$ = "0" ELSE c$ = "1"
  908.             AuxGrid(i, j, 1) = c$
  909.             AuxGrid(i, j, 2) = c$
  910.         NEXT
  911.     NEXT
  912.     FOR j = 2 TO VisibleLines - 2 ' BR offset.
  913.         FOR i = 2 TO LEN(LineAsMapped(j)) - 2 ' BR offset.
  914.             c$ = AuxGrid(i, j, 1)
  915.             a1 = VAL(AuxGrid(i - 1, j + 1, 1))
  916.             a2 = VAL(AuxGrid(i, j + 1, 1))
  917.             a3 = VAL(AuxGrid(i + 1, j + 1, 1))
  918.             a4 = VAL(AuxGrid(i - 1, j, 1))
  919.             a6 = VAL(AuxGrid(i + 1, j, 1))
  920.             a7 = VAL(AuxGrid(i - 1, j - 1, 1))
  921.             a8 = VAL(AuxGrid(i, j - 1, 1))
  922.             a9 = VAL(AuxGrid(i + 1, j - 1, 1))
  923.             t = a1 + a2 + a3 + a4 + a6 + a7 + a8 + a9
  924.             IF (c$ = "1") THEN
  925.                 SELECT CASE t
  926.                     CASE IS < 2
  927.                         AuxGrid(i, j, 2) = "0"
  928.                     CASE 2
  929.                         AuxGrid(i, j, 2) = "1"
  930.                     CASE 3
  931.                         AuxGrid(i, j, 2) = "1"
  932.                     CASE IS > 3
  933.                         AuxGrid(i, j, 2) = "0"
  934.                 END SELECT
  935.             ELSE
  936.                 IF (t = 3) THEN AuxGrid(i, j, 2) = "1"
  937.             END IF
  938.         NEXT
  939.     NEXT
  940.     FOR j = 1 TO VisibleLines
  941.         FOR i = 1 TO LEN(LineAsMapped(j)) - 1
  942.             c$ = AuxGrid(i, j, 2)
  943.             IF (c$ = "0") THEN c$ = " " ELSE c$ = CHR$(219)
  944.             AuxGrid(i, j, 1) = c$
  945.             AuxGrid(i, j, 2) = c$
  946.         NEXT
  947.     NEXT
  948.  
  949. SUB ThrowOutput
  950.     'i = NthP(ID1, ChainLimit + 1)
  951.     'FOR k = 1 TO LogTextCount
  952.     '    CALL InsertRange(i, LogText(k) + CHR$(13))
  953.     'NEXT
  954.     LogTextCount = 0
  955.     CALL MapText
  956.     ID1 = NthP(ID1, ChainLimit + 1)
  957.     CALL CalibrateCursor(ID1)
  958.     CALL CalibrateCursor(ID2)
  959.     DO WHILE (Cursor1.Y > TopIndent + TextHeight - 1)
  960.         StartIndex = NthP(StartIndex, LEN(LineAsMapped(1)) + 1)
  961.         CALL MapText
  962.         CALL CalibrateCursor(ID1)
  963.         CALL CalibrateCursor(ID2)
  964.     LOOP
  965.     ID1 = NthP(ID1, ChainLimit + 1)
  966.     CALL PrintEverything
  967.  
  968. SUB DisplayText (Col AS INTEGER, Row AS INTEGER, Shade1 AS INTEGER, Shade2 AS INTEGER, Text AS STRING)
  969.     COLOR Shade1, Shade2
  970.     _PRINTSTRING (Col, Row), Text
  971.     'LOCATE Row, Col: PRINT Text
  972.  
  973. 'REM $Include: 'sxmath.bm'
  974. 'REM $Include: 'sxript.bm'
Title: Re: Lists Linking Demo
Post by: _vince on January 22, 2019, 09:37:10 am
Interesting idea, STxExTIC.  I've tried yours before, feels like a novel text editor concept, the next vim, stevesque one could even say.  It would be interesting to see a clone of vi (way simpler than vim) in QB64 and your routines have all the functionality for it. Maybe Steve  's got something up his sleeve for the field of text editing, let us know by this eve.

FYI, my own LL routines could be repurposed to hold a single character per node like so:
Code: QB64: [Select]
  1. type nodeType
  2.   'remove this:
  3.         'str as _mem
  4.         'strLen as integer
  5.   'for:
  6.         c as string * 1
  7.  
  8.         n as _mem
  9.         p as _mem
  10.  
then you would no longer need readNode$ and writeNode and so on. Handling a string per node takes up a large portion of the code as they're a separate data structure on their own to be allocated, reallocated, and deallocated.

Next thing I will investigate is LLs in freebasic which has the C-style pointer syntax which is very expressive for these kinds of data structures.  Most of the LL functions are one liners.  LLs can also be repurposed to act as stacks, queues, trees, and other list-like structures.  Beyond LLs we have the countless variants of trees, networks, meshes and so on.
Title: Re: Lists Linking Demo
Post by: bplus on January 22, 2019, 10:50:51 am
I recognize "a linked list" as a special data structure that has some advantages over arrays specially as STxAxTIC and v have described and demonstrated with editors.

But getting back to what Steve was trying to show was a different kind of linking of lists. He didn't seem to take to ideas of databasing and the advanced database term "relational database", so I have another simpler term to try: Concatenate

Isn't Steve simply concatenating lists, adding one to another and showing manipulations of lists both individually and as a whole concatenated list. The tricky part I imagine, is dealing with mixing of different type lists.
Title: Re: Lists Linking Demo
Post by: SMcNeill on January 22, 2019, 12:55:06 pm
Isn't Steve simply concatenating lists, adding one to another and showing manipulations of lists both individually and as a whole concatenated list. The tricky part I imagine, is dealing with mixing of different type lists.

It isn’t really concatenation, as the lists “link” element by element.  “Links things together in a chain or series...”

So a list of “1, 2, 3, 4” concatetaned with “5, 6, 7, 8” produces “1,2,3,4,5,6,7,8”...  Think “dog” + “food” = “dog-food”.

This takes those 2 lists and “links” them so “1 - 5”, “2 - 6”, “3 - 7”, “4 - 8” all share the same properties and work and behave alike. 

What we’re doing here is Linking Relational Database Tables — https://www.relationaldbdesign.com/relational-database-design/module2/linking-relational-database-tables.php.

Quote
The power of relational databases stems from the fact that tables can be linked, enabling users to gain access to data across tables.

Two tables are linked when they have a matching field, that is, a field in each table containing similar data.

And that’s what the demo here does for us.  It just doesn’t seem to me that “Linking Relational Database Table Management Library” comes across as a BASIC sounding name, so “Linked Table Library” (or “Linked List Library” as I like to call it since a “LIST” *is* just a table with a single column of information) seems much simpler and more appropriate to me.