tag:blogger.com,1999:blog-92574152024-03-06T20:48:51.969-08:00BASIC ProgrammingHere are my ideas about the BASIC programming language. My company recently released a new version of BASIC for web programming called <a href="http://www.runbasic.com">Run BASIC</a>, so I have a lot to blog about.
Carl Gundel, author of Liberty BASIC
<a href="https://www.libertybasic.com">https://www.libertybasic.com</a>Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.comBlogger173125tag:blogger.com,1999:blog-9257415.post-23224191592021005392024-01-17T05:43:00.000-08:002024-01-17T05:43:38.688-08:00Organize and Share Your Code Effortlessly: Exploring the Liberty BASIC Lesson Browser<p> <span style="color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space-collapse: preserve;">The Liberty BASIC Lesson Browser is a super helpful tool for anyone using Liberty BASIC, a really user-friendly programming language. This browser isn't just for learning; it's amazing for keeping all your coding projects neat and organized.</span></p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(69,89,164,.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space-collapse: preserve;">When you use the Lesson Browser, you can easily find your way around lots of programming lessons. But the best part is how it lets you keep all your own codes and programs in one place. Whether you’re working on a small project or something big, this browser makes it easy to save your work, put it into categories, and find it again whenever you need it. This is super handy because it helps you see how much you’ve learned and find old projects quickly.</p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(69,89,164,.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space-collapse: preserve;">If you like sharing what you make with others, the Lesson Browser is great for that too. You can show your codes and programs to other people who use Liberty BASIC. This is not only fun but also a great way to get new ideas and make your work even better.</p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(69,89,164,.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space-collapse: preserve;">For educators this tool is super useful because it makes it really easy to build educational materials, and for students it provides a great way to keep all your work organized.</p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(69,89,164,.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px 0px; white-space-collapse: preserve;">So, in short, the Liberty BASIC Lesson Browser is more than just a way to learn programming. It’s a really useful tool for keeping your own coding projects organized and sharing them with friends and other coders. It's a must-have for anyone using Liberty BASIC.</p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(69,89,164,.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px 0px; white-space-collapse: preserve;"><a href="https://www.youtube.com/watch?v=Vpuo0DHionM" target="_blank">Watch a demo of the Lesson Browser!</a></p>Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-27195649014842899912024-01-16T08:41:00.000-08:002024-01-16T08:43:42.455-08:00The Heart Behind Liberty BASIC<p> As the creator of Liberty BASIC, I want to share the story behind this programming language, a project born out of my passion for making programming accessible, fun, and wondrous for everyone. My journey in the realm of coding began with the magical experience of BASIC, a language that opened the doors to the world of software creation for me. I want to bring that same sense of excitement and possibility to others through Liberty BASIC.</p><p>What makes this especially inspiring I think is that Liberty BASIC was originally meant to be a programming game, where the player programmed robots in BASIC.</p><p><span style="font-size: medium;"><b>Bringing Back the Magic of BASIC</b></span></p><p>When I realized that the BASIC I was writing for the robot game would become a real programming tool, I decided to go for it! My idea for Liberty BASIC was to recapture the spirit of the early days of BASIC. BASIC was the gateway for many into programming. It was simple, inviting, and allowed immediate interaction and results. My vision was to reignite that spark of wonder, making programming as much fun as it was for me when I first started.</p><p><b><span style="font-size: medium;">Simplicity and Approachability</span></b></p><p>At the heart of Liberty BASIC lies its simplicity and approachability. The language is designed to be easy to learn and use, especially for those who are new to programming. It’s like giving someone a set of simple, intuitive tools to start building their dream projects right away.</p><p><b><span style="font-size: medium;">Fun and Immediate Results</span></b></p><p>One of the unique features of Liberty BASIC is how it makes programming fun. I believe in the power of seeing your work come to life quickly. Beginners should be able to write a few lines of code and immediately see a window pop up, a graphic drawn, or a simple game come to life. This immediate feedback is not just rewarding; it's crucial in maintaining enthusiasm and interest in learning.</p><p><span style="font-size: medium;"><b>Liberty BASIC vs. Other Languages</b></span></p><p>While other languages like Python and JavaScript are powerful and versatile, they can be daunting for beginners. I've always tried very hard to balance simplicity with capability. </p><p><b><span style="font-size: medium;">My Vision and Journey</span></b></p><p>My personal journey with programming has always been about the joy of creating and of learning new ways to think. With Liberty BASIC, I wanted to offer a tool that makes programming feel like an adventure, not a chore. It's been heartwarming to see people of all ages take their first steps in programming with Liberty BASIC, discovering the same joy and wonder that I found years ago.</p><p>In essence, Liberty BASIC is more than just a programming language; it's a celebration of the simplicity, fun, and wonder that programming can bring. It's been a wonderful journey that I am eager to invite others to join.</p><p><b><span style="font-size: medium;">Links</span></b></p><p><span> </span><span> </span><a href="https://www.libertybasic.com" target="_blank">Liberty BASIC website</a> </p><p><span> </span><span> </span><a href="https://libertybasiccom.proboards.com" target="_blank">Liberty BASIC community forum</a> </p><p><span> </span><span> </span><a href="https://www.youtube.com/playlist?list=PL5SdDiFC8QytBvrjYvg-Qc780C8oDaqTJ" target="_blank">Liberty BASIC video playlist</a> </p>Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-35976446179683021342022-10-08T08:59:00.003-07:002022-10-08T08:59:28.324-07:00The Enduring Appeal of BASIC<p> Back in 2018 I started the BASIC Programming Language group on Facebook. Since then it has grown to more than 7000 members, and the posting has only accelerated. What I find really interesting about it is that the membership suddenly began to grow very rapidly in the last few months, more than doubling.</p><p>When a member wants to post for the first time there are a couple of questions that they need to answer, and I approve or deny the right to post based on the answers, the other groups the person belongs to and I also factor any pending comments. The overwhelming majority of the requests to post are approved.</p><p>One of the questions is, what is your first BASIC or your preferred version of BASIC?</p><p>It becomes clear that there are so many different versions of BASIC that people use and have used. I find this to be very impressive. Additionally there are a bunch of people in the group who have written their own versions of BASIC, including myself (Liberty BASIC). This sort of thing is continually ongoing. BASIC is not a dead language at all!</p><p>Another important thing is that there are people of all ages all over the world who are still using and learning BASIC.</p>Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-79332833258906951262021-09-22T08:10:00.002-07:002021-09-22T08:10:56.866-07:00End User Programming - Real Computer Literacy<div><span face="system-ui, -apple-system, system-ui, .SFNSText-Regular, sans-serif" style="color: #050505;"><span style="background-color: white; white-space: pre-wrap;">Most people will agree that it is good to understand the mechanical working of cars if you are going to drive one. It helps you to drive more safely, and if you break down somewhere you stand a chance of helping yourself out of a tough spot. When you go to the mechanic you will be able to avoid being ripped off by unscrupulous people. </span></span></div><div><span face="system-ui, -apple-system, system-ui, .SFNSText-Regular, sans-serif" style="color: #050505;"><span style="background-color: white; white-space: pre-wrap;"><br /></span></span></div><div><span face="system-ui, -apple-system, system-ui, .SFNSText-Regular, sans-serif" style="color: #050505;"><span style="background-color: white; white-space: pre-wrap;">It is no different with computers. If you learn to program computers it helps you to take advantage of them, and not the other way around. This is the real computer literacy; not the ability to operate a tablet or cell phone, or to know your way around the preferences or control panel of Windows or Mac OS. Many times I see people praising this kind of feature knowledge by young people. "Oh, young people are so smart. When I have a problem with my phone I ask my kids for help." We need to give them more than that, or else they may think more highly of themselves than they ought to.
</span></span></div><div><span face="system-ui, -apple-system, system-ui, .SFNSText-Regular, sans-serif" style="color: #050505;"><span style="background-color: white; white-space: pre-wrap;"><br /></span></span></div><div><span face="system-ui, -apple-system, system-ui, .SFNSText-Regular, sans-serif" style="color: #050505;"><span style="background-color: white; white-space: pre-wrap;">So, what vehicle can we use to give computer literacy to the people? Computer programming is the critical thing because it gives the user a real understanding of computers. For the average person to attain programming skills we don't need a complicated enterprise grade programming language, which would frustrate more than enlighten people. BASIC was the engine for people to learn programming in the early days, and still could be if Windows, Mac and Linux would just include it. Easy programming languages are missing or hidden from the user, and this causes a very real harm.</span></span></div><div><span face="system-ui, -apple-system, system-ui, .SFNSText-Regular, sans-serif" style="color: #050505;"><span style="background-color: white; white-space: pre-wrap;"><br /></span></span></div><div><span style="background-color: white; color: #050505; white-space: pre-wrap;">Why don't people create their own software anymore? They don't feel the need for it. They can just buy what they need. While this is true, there are so many times when packaged software doesn't do exactly what is needed. There are also so many kinds of useful software that could be written that will not make it onto store shelves.</span></div><div><span style="background-color: white; color: #050505; white-space: pre-wrap;"><br /></span></div><div><span style="background-color: white; color: #050505; white-space: pre-wrap;">In fact they may even wonder why they should bother. They aren't encouraged to learn programming anymore like they once were. They don't know what they're missing if you ask me. Programming is a much better way to spend brain cells than watching TV or surfing the web. Personal computing was envisioned as a way to bring the power of the computer to the individual, a very empowering idea. Being limited to using prewritten applications is like being told that as an artist you're only allowed to paint by numbers. </span></div><div><span style="background-color: white; color: #050505; white-space: pre-wrap;"><br /></span></div><div><span style="background-color: white; color: #050505; white-space: pre-wrap;">So we need an easy way to start programming. It can be really hard to create software with the programming languages endorsed by the mainstream. We have gotten away from simpler languages like BASIC, perhaps under the assumption that more complexity is better, but good computing avoids needless complexity. Even with a language like Python there is too much to learn before you get results. The Raspberry Pi computer, a device popular in schools, is a strong device for many purposes but it is too complicated to be a foundation for teaching computing to K-12 or as a first programming tool for most adult beginners.</span></div><div><span style="background-color: white; color: #050505; white-space: pre-wrap;"><br /></span></div><div><span style="background-color: white; color: #050505; white-space: pre-wrap;">Computers don't come with an easy to use programming language anymore. This is SOOOO important. It used to be that when you turned the average computer on, the first thing it did was start BASIC. You could start programming immediately, and it was very easy to pick up. Nothing bad happened if you made a mistake, and it was fun!</span></div><div><span style="background-color: white; color: #050505; white-space: pre-wrap;"><br /></span></div><div><span face="system-ui, -apple-system, system-ui, .SFNSText-Regular, sans-serif" style="color: #050505;"><span style="background-color: white; white-space: pre-wrap;">People like to say that BASIC is a bad language for teaching programming. The early versions of BASIC do have their weak points, but newer versions of BASIC are very strong for students and end users. An entire industry of computer software came out of young people using computers that started up in BASIC programming mode.</span></span></div>Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-13078864154385344262019-11-16T15:11:00.001-08:002019-11-16T15:11:05.156-08:00Have The Courage to Declutter - Best Practices Series<br />
The things in our homes each have their own purpose, and they have their proper place. In the course of time there is the inevitable accumulation of things, and this can become clutter which is a problem. This is a way to think about programming. It is not a perfect metaphor of course but I think it is useful.<br />
<br />
Clean Your Room and Take Out the Trash<br />
<br />
Living is a messy affair. We do all kinds of things in our rooms. Things like eating, opening and reading mail, getting dressed and undressed, play video games, etc. If we don't stop and put things away and throw out the trash our rooms will unlivable. How can we apply this when programming? First all if you find that you are commenting out code (in some languages comments are called remarks) then after a while your code will become harder to read and maintain. Similarly if you notice you never use some part of your code any more it might be a good idea to delete that code.<br />
<br />
Be brave and delete the old code. If you want to keep the code then save the file in a different name so that you won't lose that version of it. If you are using some kind of source code control (also known as version control) then you will never lose old code.<br />
<br />
Don't Be a Hoarder<br />
<br />
Hoarders are afraid to get rid of things and they often have many of the same kinds of things until their house fills up with so much stuff that they can't find anything and there is no room to live in their house anymore.<br />
<br />
How to implement this idea in programming? Each idea should only be expressed in one place. Do you notice sometimes when you're writing code that you are doing the same thing again and again so that when you change something then it needs to be changed everywhere you have that similar code? You need to create a subroutine or a function that does that one thing in only one place, and then call that routine from all those places where the code was duplicated. This is a kind of code refactoring.<br />
<br />
Live In a Tiny House<br />
<br />
Imagine your program must fit in a constrained memory. What is the purpose of this, you might ask? Today we have what is essentially unlimited memory in our computers. If you just sat down and wrote code every day for the rest of your life you would never be able to fill up all that memory. You might not be able to resist the temptation to add every single feature that you can to your software. People who live in a tiny house often ask themselves what are the essential things, and what can be disposed of? The more features you have, the more code you have, and the more complicated it is, and this makes it harder to extend and maintain.<br />
<br />
-"Everything should be as simple as possible, but not simpler." -- Albert Einstein<br />
<div>
<br /></div>
<div>
I hope this article is helpful to you and will give you something to incorporate into your work.</div>
Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-11787265423357415282019-11-07T05:17:00.000-08:002019-11-07T05:18:38.453-08:00One Role Per Subroutine/Function - Best Practices Series<br />
If I write the following code:<br />
<br />
call openFile "myFilename.dat"<br />
call writeDataToFile<br />
call closeFile<br />
<br />
I have three different subroutines that I am calling. The first call should open a file name named myFilename.dat. It should not do anything unrelated to opening that file. The writeData call should only write data to the file. The closeFile call should only close the file. These subroutines might have some related code that makes sense for dealing with files specific to the application, or some debug logging code or the like and that would probably be fine.<br />
<br />
But if sub openFile also opens a graphics window, or if it reinitializes a bunch of variables, or anything else that is not directly related to opening the file, that code is probably in the wrong place. Such code should be moved to its own subroutine.<br />
<br />
Why is this important?<br />
<br />
One important idea in software development is called the principle of least astonishment. As much as possible when I read code I expect that it should do precisely what it appears to be doing. Nothing more, and nothing less. Trying to avoid "What the ..!?" moments is an important goal in programming. It saves time and money and makes people's lives easier. :-)<br />
<br />
Sometimes code is initially written very clean and in a way that is compatible with this idea of one role per subroutine or function but over time it gets polluted and things get into the code which violate this principle. This is especially common when debugging because it's easy to write code during a heavy debugging session that you would not normally be willing to write when you're not debugging. Then once the bug seems to be gone we are less willing to move that 'debug quality code' to the place where it belongs, or we are not sure how to do it.<br />
<br />
Of course if you write a program such that there are no named subroutines or functions then your program is in danger of being a Big ball of mud (see https://en.wikipedia.org/wiki/Big_ball_of_mud). If you discover that this is the state of your work, your code can be greatly improved by beginning to identify sections of code that can be moved into named subroutines or functions.<br />
<br />
As a counterpoint this idea if you find that all the programs that you write are small one page long games or utilities that you bang out in a few minutes, then your programs might only be a small ball of mud. In this case you might not really benefit very much from trying to break everything down into small named subroutines.<br />
<br />Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com1tag:blogger.com,1999:blog-9257415.post-89889602084347811152019-11-05T09:47:00.000-08:002019-11-07T05:17:49.199-08:00Naming Things Well - Best Practices Series<div>
<br /></div>
<div>
Some BASIC programmers come from the experience of needing to fit their programs in 4K of RAM or less, so it feels natural to give variable names single letters such as a, b, c or I, j, k. Of course most classic BASIC interpreters don't have support more for than 2 characters for variables. Some BASICs will let you call your variable 'count' but only the c and o will be recognized as the variable name.</div>
<div>
<br /></div>
To be fair, I've seen more than a few C programmers also choose single character variable names. Bad habits are language agnostic. ;)<br />
<div>
<br /></div>
<div>
In programming languages today including Liberty BASIC, you can give your variable names and other things such as subroutines and functions longer names. What's more, computers have so much memory that we can dispense with trying to save memory with short variable names. And if you're used to using line numbers I strongly encourage you to discard them in favor of named labels. Once you are used to this it will make your programming better.</div>
<div>
<br /></div>
<div>
Why does it matter?</div>
<div>
<br /></div>
<div>
Programming is an exercise in thinking and so it is really important to pick the best possible names for the parts of your programming ideas. When you or somebody else reads your code it will help to understand the code if the variables and function/sub names are chosen well.</div>
<div>
<br /></div>
<div>
What if you are about to go to the store to buy some milk and you told your friend "I'm g to the s to b some m." How well would you be understood?</div>
<div>
<br /></div>
<div>
So, when you write code ask yourself (or the coder next to you) what is the best name for this variable or routine? Later on you may even realize there is a better name and so don't hesitate to act on that impulse and update your code with the new better name.</div>
<div>
<br /></div>
<div>
Think of your coding as a journey to discover the truth of the code, and naming things is an important part of the discovery.<br />
<br /></div>
Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-3307513335857799662018-10-26T08:57:00.000-07:002018-10-26T10:38:00.596-07:00No Software Degree? Don't Let It Stop You!<div class="graf graf--p" name="36b4">
I saw a an article over on freecodecamp.org where the author tells his story about getting a development job without a degree. I think it is so inspiring when people share their stories.<br />
<br /></div>
<div class="graf graf--p" name="36b4">
I also am an un-degreed software engineer and I’ve been working in the industry for more than 30 years.</div>
<div class="graf graf--p" name="81d3">
<br />
I assume that if you are ready to jump in to software development without doing a 4 year program, that you are passionate about writing code! If that describes you, read on!</div>
<div class="graf graf--p" name="7744">
<br />
Here are some tips.</div>
<ul class="postList">
<li class="graf graf--li" name="c398">Don’t let anyone tell you that you NEED a degree. You can go and get one, sure and if that’s what you want, great. Go do it, but it will take you years and a lot of money.</li>
<li class="graf graf--li" name="04b7">Read a lot. Consume as much programming literature as you can. Read conference proceedings. Read code. Read the History of Programming Languages, read archives of Dr. Dobbs Journal. </li>
<li class="graf graf--li" name="3722">Learn several programming languages in different paradigms. I’m familiar with BASIC, 6502 assembly, Forth, C, Objective-C, Java and Smalltalk. Don’t be a one trick pony.</li>
<li class="graf graf--li" name="d83e">Make your own software. Participate in open source projects so you can learn team programming skills. Code with friends. Create your own applications. Write some video games. Try your hand at programming tools. I wrote Liberty BASIC (a popular programming language) in my spare time and now I sell it. If you have a dossier of interesting stuff that you’ve done, it will be easier to get hired. Haven’t done anything interesting? The degree may not be enough.</li>
<li class="graf graf--li" name="d237">Network like crazy. Almost every job I’ve landed I landed because of people I met at the store, at church, at conferences (that I paid to attend myself), etc. Join some programming groups on Facebook and meet local people using meetup.com. This can be really important.</li>
<li class="graf graf--li" name="a297">Be ready to explain what you know. When you do get that interview, who will hire you if you can’t show on the whiteboard what you learned from your work. Give them a post mortem on your own code. Be ready to say what you could have done better.</li>
</ul>
<div class="graf graf--p" name="e9dc">
Good luck and please check out my Liberty BASIC product! <a href="http://www.libertybasic.com/">http://www.libertybasic.com</a></div>
<div class="graf graf--p" name="e9dc">
See you around!</div>
<div class="graf graf--p" name="e9dc">
<br /></div>
Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com1tag:blogger.com,1999:blog-9257415.post-23650931409909937022018-09-07T06:32:00.000-07:002018-09-07T06:32:22.167-07:00Win a free Liberty BASIC software!<div style="-webkit-text-stroke-width: 0px; background-color: transparent; color: black; font-family: Times New Roman; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<span style="font-family: inherit;"><span style="-webkit-text-stroke-width: 0px; background-color: transparent; color: #483c32; display: inline; float: none; font-family: inherit; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; word-wrap: break-word;">We are having a referral contest until the end of October! You can win a copy of the Liberty BASIC programming software. All you need to do is tell five friends who you think will enjoy Liberty BASIC to email us saying they learned about Liberty BASIC from you!</span></span></div>
<div style="-webkit-text-stroke-width: 0px; background-color: transparent; color: black; font-family: Times New Roman; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<br /></div>
<a href="http://libertybasic.com/referralcontest.html" target="_blank">Read more about it here!</a>Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-10478906668409525782018-09-06T08:43:00.000-07:002018-09-06T08:43:12.355-07:00New Liberty BASIC Projects Area<span style="font-family: inherit;">I've created a new area on the Liberty BASIC Community Forum over at Proboards here:</span><br />
<br />
<a href="http://libertybasiccom.proboards.com/board/20/community-projects" target="_blank">http://libertybasiccom.proboards.com/board/20/community-projects</a><br />
<br />
<span style="font-family: inherit;"><span style="-webkit-text-stroke-width: 0px; background-color: transparent; color: #483c32; display: inline !important; float: none; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; word-wrap: break-word;">Here is copy from a post I made there about the purpose of the board:</span></span><br />
<blockquote class="tr_bq">
<div style="-webkit-text-stroke-width: 0px; background-color: transparent; color: black; font-family: Times New Roman; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">
<span style="font-family: inherit;"><span style="-webkit-text-stroke-width: 0px; background-color: transparent; color: #483c32; display: inline; float: none; font-family: inherit; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; word-wrap: break-word;">I created this area of the board for a specific reason. I want to create libraries free code for specific purposes and also some programs for the specific purpose of promoting Liberty BASIC.</span><br style="-webkit-text-stroke-width: 0px; background-color: transparent; color: #483c32; font-family: inherit; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; max-height: 1000000px; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; word-wrap: break-word;" /><br style="-webkit-text-stroke-width: 0px; background-color: transparent; color: #483c32; font-family: inherit; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; max-height: 1000000px; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; word-wrap: break-word;" /><span style="-webkit-text-stroke-width: 0px; background-color: transparent; color: #483c32; display: inline; float: none; font-family: inherit; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; word-wrap: break-word;">So, for example:</span></span></div>
<ul style="-webkit-text-stroke-width: 0px; background-attachment: scroll; background-clip: border-box; background-color: transparent; background-image: none; background-origin: padding-box; background-position-x: 0px; background-position-y: 0px; background-repeat: repeat; background-size: auto; border-bottom-color: rgb(72, 60, 50); border-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat: stretch; border-image-slice: 100%; border-image-source: none; border-image-width: 1; border-left-color: rgb(72, 60, 50); border-left-style: none; border-left-width: 0px; border-right-color: rgb(72, 60, 50); border-right-style: none; border-right-width: 0px; border-top-color: rgb(72, 60, 50); border-top-style: none; border-top-width: 0px; color: #483c32; font-family: Times New Roman; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; list-style-image: none; list-style-position: outside; list-style-type: disc; margin-bottom: 0px; margin-left: 31px; margin-right: 0px; margin-top: 0px; max-height: 1000000px; orphans: 2; outline-color: invert; outline-style: none; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; word-wrap: break-word;">
<li style="background-attachment: scroll; background-clip: border-box; background-color: transparent; background-image: none; background-origin: padding-box; background-position-x: 0px; background-position-y: 0px; background-repeat: repeat; background-size: auto; border-bottom-color: rgb(72, 60, 50); border-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat: stretch; border-image-slice: 100%; border-image-source: none; border-image-width: 1; border-left-color: rgb(72, 60, 50); border-left-style: none; border-left-width: 0px; border-right-color: rgb(72, 60, 50); border-right-style: none; border-right-width: 0px; border-top-color: rgb(72, 60, 50); border-top-style: none; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; max-height: 1000000px; outline-color: invert; outline-style: none; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; word-wrap: break-word;"><span style="font-family: inherit;">A game framework and some examples. Side scrolling games, platform games, etc., with sprites, sound effects, background music that can use the keyboard, mouse, or joystick. etc.</span></li>
<li style="background-attachment: scroll; background-clip: border-box; background-color: transparent; background-image: none; background-origin: padding-box; background-position-x: 0px; background-position-y: 0px; background-repeat: repeat; background-size: auto; border-bottom-color: rgb(72, 60, 50); border-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat: stretch; border-image-slice: 100%; border-image-source: none; border-image-width: 1; border-left-color: rgb(72, 60, 50); border-left-style: none; border-left-width: 0px; border-right-color: rgb(72, 60, 50); border-right-style: none; border-right-width: 0px; border-top-color: rgb(72, 60, 50); border-top-style: none; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; max-height: 1000000px; outline-color: invert; outline-style: none; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; word-wrap: break-word;"><span style="font-family: inherit;">A business application including forms, an ODBC database, printed output (tables, forms, bar charts, histograms)</span></li>
<li style="background-attachment: scroll; background-clip: border-box; background-color: transparent; background-image: none; background-origin: padding-box; background-position-x: 0px; background-position-y: 0px; background-repeat: repeat; background-size: auto; border-bottom-color: rgb(72, 60, 50); border-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat: stretch; border-image-slice: 100%; border-image-source: none; border-image-width: 1; border-left-color: rgb(72, 60, 50); border-left-style: none; border-left-width: 0px; border-right-color: rgb(72, 60, 50); border-right-style: none; border-right-width: 0px; border-top-color: rgb(72, 60, 50); border-top-style: none; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; max-height: 1000000px; outline-color: invert; outline-style: none; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; word-wrap: break-word;"><span style="font-family: inherit;">A graphical editor - a mini CAD program or similar</span></li>
<li style="background-attachment: scroll; background-clip: border-box; background-color: transparent; background-image: none; background-origin: padding-box; background-position-x: 0px; background-position-y: 0px; background-repeat: repeat; background-size: auto; border-bottom-color: rgb(72, 60, 50); border-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat: stretch; border-image-slice: 100%; border-image-source: none; border-image-width: 1; border-left-color: rgb(72, 60, 50); border-left-style: none; border-left-width: 0px; border-right-color: rgb(72, 60, 50); border-right-style: none; border-right-width: 0px; border-top-color: rgb(72, 60, 50); border-top-style: none; border-top-width: 0px; font-size: 16px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; max-height: 1000000px; outline-color: invert; outline-style: none; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; word-wrap: break-word;"><span style="font-family: inherit;">Hardware interfacing - a monitor program for experimenting with serial devices</span></li>
</ul>
<div style="-webkit-text-stroke-width: 0px; background-attachment: scroll; background-clip: border-box; background-color: transparent; background-image: none; background-origin: padding-box; background-position-x: 0px; background-position-y: 0px; background-repeat: repeat; background-size: auto; border-bottom-color: rgb(72, 60, 50); border-bottom-style: none; border-bottom-width: 0px; border-image-outset: 0; border-image-repeat: stretch; border-image-slice: 100%; border-image-source: none; border-image-width: 1; border-left-color: rgb(72, 60, 50); border-left-style: none; border-left-width: 0px; border-right-color: rgb(72, 60, 50); border-right-style: none; border-right-width: 0px; border-top-color: rgb(72, 60, 50); border-top-style: none; border-top-width: 0px; color: #483c32; font-family: Times New Roman; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; max-height: 1000000px; orphans: 2; outline-color: invert; outline-style: none; outline-width: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; word-wrap: break-word;">
<span style="font-family: inherit;"><br style="max-height: 1000000px; word-wrap: break-word;" />Suggestions welcome. Is there any particular thing you know how to do well, or that you would like to be able to do in Liberty BASIC? Let's make these things into actual reusable code that people can use, and that can be included with Liberty BASIC.</span></div>
</blockquote>
I will also blog here about these projects as they progress.Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-37450082043938422642018-09-04T09:19:00.000-07:002018-09-04T09:19:10.776-07:00New blog - The 6502 Shack<span style="-webkit-text-stroke-width: 0px; background-color: transparent; color: #333333; display: inline !important; float: none; font-family: Verdana,Arial,Sans-serif; font-size: 13.33px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; line-height: 17.33px; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">I'm a big fan of the 8-bit computers based on the 6502.</span><br />
<span style="-webkit-text-stroke-width: 0px; background-color: transparent; color: #333333; display: inline !important; float: none; font-family: Verdana,Arial,Sans-serif; font-size: 13.33px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; line-height: 17.33px; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;"><br /></span>
<span style="-webkit-text-stroke-width: 0px; background-color: transparent; color: #333333; display: inline !important; float: none; font-family: Verdana,Arial,Sans-serif; font-size: 13.33px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; line-height: 17.33px; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">I've created a new blog dedicated to the MOS 6502 microprocessor and the computers that are built on it, and also a new Facebook group for it. Read more about it </span><a href="http://6502shack.blogspot.com/2018/09/" style="-webkit-text-stroke-width: 0px; background-color: transparent; color: #336699; font-family: Verdana,Arial,Sans-serif; font-size: 13.33px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: underline; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;" target="_blank">here</a><span style="-webkit-text-stroke-width: 0px; background-color: transparent; color: #333333; display: inline !important; float: none; font-family: Verdana,Arial,Sans-serif; font-size: 13.33px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; line-height: 17.33px; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px;">.
</span><b></b><i></i><u></u><sub></sub><sup></sup><strike></strike>Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-34042480316409124902017-08-02T19:35:00.000-07:002017-08-02T19:54:10.800-07:00Raspberry Pi Deluxe Starter Kit Giveaway!<span style="font-family: inherit;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span>
</span><br />
<span style="font-family: inherit;"><span style="font-family: "times" , "times new roman" , serif;">We are giving away a deluxe Raspberry Pi kit, and this includes all kinds of nice accessories including an electronics learning lab. No purchase is required, so enter by Aug 31, 2017 to be included in the raffle.</span></span><br />
<br /><span style="font-family: inherit;"><span style="background-color: white;"><span style="font-family: "times" , "times new roman" , serif;">Check out the video here for details about the kit! <a href="https://youtu.be/toln-Z_z4RY" style="color: #336633; text-decoration: none;" target="_blank">https://youtu.be/toln-Z_z4RY</a></span></span></span><br />
<span style="background-color: white;"><br /></span><span style="font-family: inherit;"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white;">To enter the drawing, send an email to carlg@justbasic.com with the subject Raspberry Pi Contest, and we will send you a confirmation email. The winner will be announced at the end of August 2017.</span></span></span><br />
<span style="background-color: white;"><br /></span><span style="font-family: inherit;"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white;">Please share this information with your friends.</span></span></span><br />
<br />
<span style="font-family: inherit;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span></span>
<span style="font-family: inherit;"><span style="background-color: white;"><span style="font-family: "times" , "times new roman" , serif;"><a href="https://youtu.be/toln-Z_z4RY" style="color: #336633; text-decoration: none;" target="_blank"><br /></a></span></span></span>
<span style="font-family: inherit;"><span style="font-family: "times" , "times new roman" , serif;"><span style="background-color: white;"><br /></span></span></span>Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-3010563628389587822016-08-22T06:15:00.000-07:002016-08-22T06:15:00.912-07:00Book - Programming for the Absolute Beginner 2nd Edition<span style="font-weight: normal;"><span style="font-family: inherit;"><span class="a-size-extra-large" id="productTitle" style="box-sizing: border-box; line-height: 1.2 !important; text-rendering: optimizelegibility;">Programming for the Absolute Beginner</span> <span class="a-size-large a-color-secondary a-text-normal" id="bookEdition" style="box-sizing: border-box; line-height: 1.3 !important; text-rendering: optimizelegibility;">2nd Edition by Jerry Ford</span></span></span><br />
<span style="font-weight: normal;"><span style="font-family: inherit;"><span class="a-size-large a-color-secondary a-text-normal" style="box-sizing: border-box; line-height: 1.3 !important; text-rendering: optimizelegibility;"><br /></span></span></span>
<span class="a-size-large a-color-secondary a-text-normal" style="box-sizing: border-box; line-height: 1.3 !important; text-rendering: optimizelegibility;"><span style="font-family: inherit;">I was excited to see that a second edition of Jerry Ford's programming book was recently released. It uses Just BASIC (all examples also compatible with Liberty BASIC) to teach the fundamentals of programming.</span></span><br />
<br />
<a href="https://www.amazon.com/Programming-Absolute-Beginner-Jerry-Ford/dp/1305504437/ref=sr_1_2?ie=UTF8&qid=1471869789&sr=8-2&keywords=jerry+ford+programming" target="_blank">Jump to Amazon's link</a><br />
<br />
Here is the table of contents. :-)<br />
<br />
1 Introduction to Programming<br />
2 Creating Programs with Just BASIC<br />
3 Creating Graphical User Interfaces<br />
4 Working with Variables and Arrays<br />
5 Making Decisions with Conditional Logic<br />
6 Using Loops to Process Data<br />
7 Improving Program Organization with Functions and Subroutines<br />
8 Working with Text Files<br />
9 Working with Sound and Graphics<br />
10 Arcade-Style Computer Game Development<br />
11 Debugging Your ApplicationsCarl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-46266093364714610602016-08-19T05:41:00.001-07:002016-08-19T05:41:45.803-07:00Graphing Data - Setting the stageIf I have a set of data for sales, or temperature, or mosquito populations, or anything at all and I want to plot it on an X/Y graph, what are my choices for layout?<br />
<div>
<br /></div>
<div>
Should our graphing library figure out what the ranges are and set its own scaling? Should it require that we tell it up front what the X and Y scales are? Maybe it can even be designed to allow for changing the scale on the fly?<br />
<br />
It would be great if our data plotting graphics library could handle plotting to screen, saving that to a file as a bitmap, and also plotting to a printer.</div>
<div>
<br /></div>
<div>
How about data sources and formats? Should we design it to accept one or more strings of delimited values? In the graphing example at <a href="http://runbasic.com/">runbasic.com</a> it allows you to upload a CSV file with data to plot. Maybe as an interesting example I should find a downloadable file from a scientific website and the project should be to plot a graph from that?<br />
<br />
Feedback welcome. More to come.</div>
Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com1tag:blogger.com,1999:blog-9257415.post-27905461800023492882016-08-08T05:04:00.000-07:002016-08-08T05:04:48.493-07:00Graphing dataI get a lot of questions about how to draw graphs involving progressions of numbers, and comparisons of trends, etc. Liberty BASIC doesn't have a built in graphing function, but it does support rich graphics drawing.<br />
<br />
So if you're looking for a way to draw graphs of money, web traffic, rainfall, or whatever else stay tuned over the next couple of weeks. We're going to blaze a trail!<br />
<br />
There are at least a couple of options for solving this problem.<br />
<br />
<ul>
<li>Export data out to a CSV file and use Excel to plot graphs</li>
<li>Use Liberty BASIC's graphics drawing features and draw the graphs ourselves</li>
</ul>
<div>
We are going to draw the graphs ourselves.</div>
<div>
<br /></div>
<div>
Impatient for the next post? Check out this link!</div>
<div>
<br /></div>
<div>
<a href="https://lbpe.wikispaces.com/Graphics101plotting">https://lbpe.wikispaces.com/Graphics101plotting</a></div>
<div>
<br /></div>
<div>
Stay tuned!</div>
Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-88567087520597755252016-08-02T06:46:00.000-07:002016-08-18T05:11:59.430-07:00Blast from the past - Whatever happened to PEEK and POKE?<span style="font-family: "times" , "times new roman" , serif;"><i>I am reposting the following blog entry from ten years ago because it has been one of the most popular posts ever according to Blogger's statistics graph. The link at the end of the post was broken, so I updated it.</i></span><br />
<span style="font-family: "times" , "times new roman" , serif;"><i><br />Enjoy!</i></span><br />
<div class="post-body entry-content" id="post-body-114290859189874683" itemprop="description articleBody">
<span style="font-family: "times" , "times new roman" , serif;"><br /></span></div>
<div class="post-body entry-content" id="post-body-114290859189874683" itemprop="description articleBody">
<span style="font-family: inherit;">Sometimes I'm asked how to PEEK and POKE using Liberty BASIC. The short answer to this is, you can't. The long answer is more complicated.<br /><br />The original home computers (like the classic Commodore 64, TRS-80, and Apple II models) were designed to be completely open to their owners. Most of the different parts of the computer like the sound, graphics, keyboard and joystick (there were no mice back then) were controlled by mapping them to different memory locations. So, the built-in commands didn't do everything you need? It was common to control the computer's equipment directly by sticking values into the memory locations that control that equipment, and reading the status back out. This was done with POKE and PEEK. This was a lot of fun, and usually useful too.<br /><br />Since these early machines didn't multitask it was pretty safe to steal control of things away from the BASIC interpreter (which was a much operating system as there was). Then computers started running Windows, the Mac OS, Linux, etc. and allowed more than one program to run at a time. PEEK and POKE became problematic because if one program decided to mess with the screen for example, it might interfere with what other programs need to do their thing. Not only that, but computers today all have different kinds of hardware in them, so even if you could PEEK and POKE the exact memory locations would be different from machine to machine. So that's the bad news. :-(<br /><br />The good news is that we can still have a power trip. How? Your operating system manages all the hardware for you behind operating system functions. These functions make every computer look more or less the same to the programmer. You can use these functions to do a lot of powerful things and most languages have a way to use them. For example Liberty BASIC programmers can use the CALLDLL command to make Windows API calls, which are the operating system calls of the Windows operating system. These are more complicated in general (and you can fill a whole bookshelf with information about them) than the old fashioned PEEK and POKE, but at least we aren't left without some way to pull rank on our computers. ;-)<br /><br />So if you're missing the power and coolness of PEEK and POKE, why not try your hand at API calls?<br /><br />Here is a useful link to get you started:</span></div>
<span style="font-family: inherit;"><span style="font-family: "times" , "times new roman" , serif;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif;"><a href="http://www.libertybasicuniversity.com/lbnews/nl108/index.htm">http://www.libertybasicuniversity.com/lbnews/nl108/index.htm</a></span></span>Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-60191190209815837722016-08-02T06:31:00.000-07:002016-08-02T06:31:23.268-07:00High DPI IssuesThese days we see the arrival of very high resolution displays such as Apple's retina screens and the 4K monitors. These are very cool, but for programmers they can be a real pain in the side.<br />
<br />
Any application designed for a normal monitor will be tiny when viewed on a very high resolution monitor. Windows provides a way to make things larger on screen so that the user isn't left reaching for a magnifying glass, but the effect isn't consistently applied to all the widgets and fonts, so that the user is left with an unsatisfying and unsatisfactory result.<br />
<br />
The programming is left with the job of cleaning this up.<br />
<br />
Check out the ongoing thread about this in our forum.<br />
<br />
<a href="http://libertybasic.conforums.com/index.cgi?board=general&action=display&num=1456442864&start=0">http://libertybasic.conforums.com/index.cgi?board=general&action=display&num=1456442864&start=0</a>Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-80063916352799815272016-08-02T06:01:00.001-07:002016-08-02T06:01:04.318-07:00Dictionary lookup - bug fixesOne of our eagle-eyed forum members noticed a bug in our dictionary code (thanks to tsh!). In a couple of places the code that dealt with keys was not looking for the end of the key name. This caused problems when two keys started the same. For example let's say we have a key "name" and another key "names of next of kin". The second key starts with "name", and the code wasn't written to avoid a false detection of this sort.<br />
<br />
The solution to this problem is to fully qualify the key names by adding the "~value~" tag into the detection code so that when we look for "name" we are actually looking for a match on "~key~name~value~" and not "~key~name", which would give us a false positive if we looking at any key that happened to start with "name"<br />
<br />
Here is the fixed version of our dictionary inspector. Enjoy!<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> nomainwin</span><br />
<span style="font-family: Courier New, Courier, monospace;"> WindowWidth = 555</span><br />
<span style="font-family: Courier New, Courier, monospace;"> WindowHeight = 438</span><br />
<span style="font-family: Courier New, Courier, monospace;"> dim keys$(1000)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> dim info$(10, 10)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> global dictionary$, keyCount, lastKey$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call readDictionary</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> texteditor #main.value, 175, 7, 360, 365</span><br />
<span style="font-family: Courier New, Courier, monospace;"> listbox #main.keys, keys$(), [keySelected], 5, 7, 160, 365</span><br />
<span style="font-family: Courier New, Courier, monospace;"> menu #main, "Key", "New", [newKey], "Delete", [deleteKey]</span><br />
<span style="font-family: Courier New, Courier, monospace;"> menu #main, "Edit"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> open "Dictionary inspector" for window as #main</span><br />
<span style="font-family: Courier New, Courier, monospace;"> #main "trapclose [quit]"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> #main.keys "singleclickselect"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> #main.value "!autoresize";</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call loadKeys</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">[main.inputLoop] 'wait here for input event</span><br />
<span style="font-family: Courier New, Courier, monospace;"> wait</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">[newKey] 'ask the user for a new key</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call saveValue</span><br />
<span style="font-family: Courier New, Courier, monospace;"> prompt "Enter a name for the key."; newKey$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if newKey$ <> "" then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call setValueByName newKey$, ""</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call loadKeys</span><br />
<span style="font-family: Courier New, Courier, monospace;"> #main.keys "select "; newKey$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> #main.value "!cls";</span><br />
<span style="font-family: Courier New, Courier, monospace;"> #main.value "!setfocus";</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call collectGarbage</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call writeDictionary</span><br />
<span style="font-family: Courier New, Courier, monospace;"> lastKey$ = newKey$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;"> wait</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">[deleteKey] 'left for later</span><br />
<span style="font-family: Courier New, Courier, monospace;"> notice "Delete not implemented yet."</span><br />
<span style="font-family: Courier New, Courier, monospace;"> wait</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">[keySelected] 'a key in the list was selected</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call saveValue</span><br />
<span style="font-family: Courier New, Courier, monospace;"> #main.keys "selection? selectedKey$"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> selectedValue$ = getValue$(selectedKey$)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> #main.value "!contents selectedValue$";</span><br />
<span style="font-family: Courier New, Courier, monospace;"> lastKey$ = selectedKey$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> wait</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">[quit] 'End the program</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call saveValue</span><br />
<span style="font-family: Courier New, Courier, monospace;"> close #main</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">sub saveValue 'if the value is changed, save it</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if lastKey$ <> "" then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> #main.value "!modified? modified$";</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if modified$ = "true" then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> #main.value "!contents? saveThisValue$";</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call setValueByName lastKey$, saveThisValue$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call collectGarbage</span><br />
<span style="font-family: Courier New, Courier, monospace;"> call writeDictionary</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;">end sub</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">function getKeys$(delimiter$)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> global keyCount</span><br />
<span style="font-family: Courier New, Courier, monospace;"> pointer = 1</span><br />
<span style="font-family: Courier New, Courier, monospace;"> while pointer <> 0</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 'get the next key</span><br />
<span style="font-family: Courier New, Courier, monospace;"> pointer = instr(dictionary$, "~key~", pointer)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if pointer then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> keyPointer = pointer + 5</span><br />
<span style="font-family: Courier New, Courier, monospace;"> pointer = instr(dictionary$, "~value~", pointer)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> key$ = mid$(dictionary$, keyPointer, pointer - keyPointer)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if instr(keyList$, "~key~" + key$ + "~value~") = 0 then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> getKeys$ = getKeys$ + key$ + delimiter$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> keyList$ = keyList$ + "~key~" + key$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> keyCount = keyCount + 1</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;"> wend</span><br />
<span style="font-family: Courier New, Courier, monospace;">end function</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">sub writeDictionary</span><br />
<span style="font-family: Courier New, Courier, monospace;"> open "dictionary.dat" for output as #writeDict</span><br />
<span style="font-family: Courier New, Courier, monospace;"> print #writeDict, dictionary$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> close #writeDict</span><br />
<span style="font-family: Courier New, Courier, monospace;">end sub</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">sub readDictionary</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if fileExists(DefaultDir$, "dictionary.dat") then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> open "dictionary.dat" for input as #readDict</span><br />
<span style="font-family: Courier New, Courier, monospace;"> length = lof(#readDict)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> dictionary$ = input$(#readDict, length)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> close #readDict</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;">end sub</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">sub collectGarbage</span><br />
<span style="font-family: Courier New, Courier, monospace;"> pointer = 1</span><br />
<span style="font-family: Courier New, Courier, monospace;"> while pointer > 0</span><br />
<span style="font-family: Courier New, Courier, monospace;"> 'get the next key</span><br />
<span style="font-family: Courier New, Courier, monospace;"> pointer = instr(dictionary$, "~key~", pointer)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if pointer then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> keyPointer = pointer + 5</span><br />
<span style="font-family: Courier New, Courier, monospace;"> pointer = instr(dictionary$, "~value~", pointer)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> key$ = mid$(dictionary$, keyPointer, pointer - keyPointer)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if instr(keyList$, "~key~" + key$ + "~value~") = 0 then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> value$ = getValue$(key$)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> newDictionary$ = "~key~" + key$ + "~value~" + value$ + newDictionary$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> keyList$ = keyList$ + "~key~" + key$ + "~value~"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;"> wend</span><br />
<span style="font-family: Courier New, Courier, monospace;"> dictionary$ = newDictionary$</span><br />
<span style="font-family: Courier New, Courier, monospace;">end sub</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">sub setValueByName key$, value$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> dictionary$ = "~key~"+key$+"~value~"+value$+dictionary$</span><br />
<span style="font-family: Courier New, Courier, monospace;">end sub</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">function getValue$(key$)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> getValue$ = chr$(0)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> keyPosition = instr(dictionary$, "~key~"+key$+"~value~")</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if keyPosition > 0 then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> keyPosition = keyPosition + 5 'skip over key tag</span><br />
<span style="font-family: Courier New, Courier, monospace;"> valuePosition = instr(dictionary$, "~value~", keyPosition)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if valuePosition > 0 then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> valuePosition = valuePosition + 7 'skip over value tag</span><br />
<span style="font-family: Courier New, Courier, monospace;"> endPosition = instr(dictionary$, "~key~", valuePosition)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if endPosition > 0 then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> getValue$ = mid$(dictionary$, valuePosition, endPosition - valuePosition)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> else</span><br />
<span style="font-family: Courier New, Courier, monospace;"> getValue$ = mid$(dictionary$, valuePosition)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;">end function</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">sub loadKeys</span><br />
<span style="font-family: Courier New, Courier, monospace;"> keyList$ = getKeys$("~")</span><br />
<span style="font-family: Courier New, Courier, monospace;"> redim keys$(keyCount)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> for item = 1 to keyCount</span><br />
<span style="font-family: Courier New, Courier, monospace;"> keys$(item-1) = word$(keyList$, item, "~")</span><br />
<span style="font-family: Courier New, Courier, monospace;"> next item</span><br />
<span style="font-family: Courier New, Courier, monospace;"> #main.keys "reload"</span><br />
<span style="font-family: Courier New, Courier, monospace;">end sub</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">function fileExists(path$, filename$) ' Does file exist?</span><br />
<span style="font-family: Courier New, Courier, monospace;"> files path$, filename$, info$(</span><br />
<span style="font-family: Courier New, Courier, monospace;"> fileExists = val(info$(0, 0)) > 0</span><br />
<span style="font-family: Courier New, Courier, monospace;">end function</span><br />
<div>
<br /></div>
<br />Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-19772461747305561352016-07-20T05:42:00.000-07:002016-07-20T06:13:22.593-07:00A dictionary lookup mini applicationHere is a simple demo application for our keyed lookup library in development. It opens a window with keys on the left, and a text editor on the right. You can add new keys and edit the values for those keys by changing text on the right. The values are saved to the file dictionary.dat.<br />
<br />
We will enhance this code for a couple more blog entries before we move on to some other project. :-)<br />
<br />
Enjoy!<br />
<br /><span style="font-family: "Courier New", Courier, monospace;"> nomainwin<br /> WindowWidth = 555<br /> WindowHeight = 438</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> dim keys$(1000)<br /> dim info$(10, 10)<br /> global dictionary$, keyCount, lastKey$<br /> call readDictionary</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;"> texteditor #main.value, 175, 7, 360, 365<br /> listbox #main.keys, keys$(), [keySelected], 5, 7, 160, 365</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> menu #main, "Key", "New", [newKey], "Delete", [deleteKey]<br /> menu #main, "Edit"</span><br />
<span style="font-family: "Courier New", Courier, monospace;"> open "Dictionary inspector" for window as #main<br /> #main "trapclose [quit]"<br /> #main.keys "singleclickselect"<br /> #main.value "!autoresize";<br /> call loadKeys</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">[main.inputLoop] 'wait here for input event<br /> wait</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">[newKey] 'ask the user for a new key<br /> call saveValue<br /> prompt "Enter a name for the key."; newKey$<br /> if newKey$ <> "" then<br /> call setValueByName newKey$, ""<br /> call loadKeys<br /> #main.keys "select "; newKey$<br /> #main.value "!cls";<br /> #main.value "!setfocus";<br /> call writeDictionary<br /> lastKey$ = newKey$<br /> end if<br /> wait</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">[deleteKey] 'left for later<br /> notice "Delete not implemented yet."<br /> wait</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">[keySelected] 'a key in the list was selected<br /> call saveValue<br /> #main.keys "selection? selectedKey$"<br /> selectedValue$ = getValue$(selectedKey$)<br /> #main.value "!contents selectedValue$";<br /> lastKey$ = selectedKey$<br /> wait</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">[quit] 'End the program<br /> call saveValue<br /> close #main<br /> end</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">sub saveValue 'if the value is changed, save it<br /> if lastKey$ <> "" then<br /> #main.value "!modified? modified$";<br /> if modified$ = "true" then<br /> #main.value "!contents? saveThisValue$";<br /> call setValueByName lastKey$, saveThisValue$<br /> call collectGarbage<br /> call writeDictionary<br /> end if<br /> end if<br />end sub</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">function getKeys$(delimiter$)<br /> global keyCount<br /> pointer = 1<br /> while pointer > 0<br /> 'get the next key<br /> pointer = instr(dictionary$, "~key~", pointer)<br /> if pointer then<br /> keyPointer = pointer + 5<br /> pointer = instr(dictionary$, "~value~", pointer)<br /> key$ = mid$(dictionary$, keyPointer, pointer - keyPointer)<br /> if instr(keyList$, "~key~" + key$) = 0 then<br /> getKeys$ = getKeys$ + key$ + delimiter$<br /> keyList$ = keyList$ + "~key~" + key$<br /> keyCount = keyCount + 1<br /> end if<br /> end if<br /> wend<br />end function</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">sub writeDictionary<br /> open "dictionary.dat" for output as #writeDict<br /> print #writeDict, dictionary$<br /> close #writeDict<br />end sub</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">sub readDictionary<br /> if fileExists(DefaultDir$, "dictionary.dat") then<br /> open "dictionary.dat" for input as #readDict<br /> length = lof(#readDict)<br /> dictionary$ = input$(#readDict, length)<br /> close #readDict<br /> end if<br />end sub</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">sub collectGarbage<br /> pointer = 1<br /> while pointer > 0<br /> 'get the next key<br /> pointer = instr(dictionary$, "~key~", pointer)<br /> if pointer then<br /> keyPointer = pointer + 5<br /> pointer = instr(dictionary$, "~value~", pointer)<br /> key$ = mid$(dictionary$, keyPointer, pointer - keyPointer)<br /> if instr(keyList$, key$) = 0 then<br /> value$ = getValue$(key$)<br /> newDictionary$ = "~key~" + key$ + "~value~" + value$ + newDictionary$<br /> keyList$ = keyList$ + key$<br /> end if<br /> end if<br /> wend<br /> dictionary$ = newDictionary$<br />end sub</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br />sub setValueByName key$, value$<br /> dictionary$ = "~key~"+key$+"~value~"+value$+dictionary$<br />end sub</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">function getValue$(key$)<br /> getValue$ = chr$(0)<br /> keyPosition = instr(dictionary$, "~key~"+key$)<br /> if keyPosition > 0 then<br /> keyPosition = keyPosition + 5 'skip over key tag<br /> valuePosition = instr(dictionary$, "~value~", keyPosition)<br /> if valuePosition > 0 then<br /> valuePosition = valuePosition + 7 'skip over value tag<br /> endPosition = instr(dictionary$, "~key~", valuePosition)<br /> if endPosition > 0 then<br /> getValue$ = mid$(dictionary$, valuePosition, endPosition - valuePosition)<br /> else<br /> getValue$ = mid$(dictionary$, valuePosition)<br /> end if<br /> end if<br /> end if<br />end function</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">sub loadKeys<br /> keyList$ = getKeys$("~")<br /> redim keys$(keyCount)<br /> for item = 1 to keyCount<br /> keys$(item-1) = word$(keyList$, item, "~")<br /> next item<br /> #main.keys "reload"<br />end sub</span><br />
<span style="font-family: "Courier New", Courier, monospace;"><br /></span>
<span style="font-family: "Courier New", Courier, monospace;">function fileExists(path$, filename$) ' Does file exist?<br /> files path$, filename$, info$(<br /> fileExists = val(info$(0, 0)) > 0<br />end function</span><br />
<span style="font-family: "courier new";"><br /></span>Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-21196928275351754082016-07-15T06:00:00.002-07:002016-07-15T06:01:37.942-07:00Dictionary lookup - getting the keysWhen you have an array you can simply loop through the contents to examine what's there, but when you have a dictionary you need to have the list of keys so that you can look up each value in the dictionary. For that, we need a getKeys$() function. The following function returns a single string with the keys from our global dictionary$ variable, each separated by a delimiter that we can specify.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">function getKeys$(delimiter$)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> pointer = 1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while pointer > 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'get the next key</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> pointer = instr(dictionary$, "~key~", pointer)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if pointer then</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> keyPointer = pointer + 5</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> pointer = instr(dictionary$, "~value~", pointer)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> key$ = mid$(dictionary$, keyPointer, pointer - keyPointer)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if instr(keyList$, "~key~" + key$) = 0 then</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> getKeys$ = getKeys$ + key$ + delimiter$</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> keyList$ = keyList$ + "~key~" + key$</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> end if</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> end if</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> wend</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">end function</span><br />
<br />
Once have this string we can tease out each key. Here is an quick example that shows how to do this. The variable allKeys$ will hold all the keys, each separated by "~". Then we use the word$() function to get each key.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">global dictionary$</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"></span><br />
<span style="font-family: "courier new" , "courier" , monospace;">call setValueByName "first", "Tom"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">call setValueByName "last", "Thumb"</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">call setValueByName "phone", "555-555-1234"</span><br />
<span style="font-family: "courier new";"></span><br />
<span style="font-family: "courier new" , "courier" , monospace;"></span><span style="font-family: "courier new";">allKeys$ = getKeys$("~")</span><br />
<span style="font-family: "courier new";">print allKeys$</span><br />
<span style="font-family: "courier new";"><br /></span>
<span style="font-family: "courier new";">key = 1</span><br />
<span style="font-family: "courier new";">while word$(allKeys$, key, "~") <> ""</span><br />
<span style="font-family: "courier new";"> key$ = word$(allKeys$, key, "~")</span><br />
<span style="font-family: "courier new";"> print "Key number "; key; " is "; key$</span><br />
<span style="font-family: "courier new";"> print " value = "; getValue$(key$)</span><br />
<span style="font-family: "courier new";"> key = key + 1</span><br />
<span style="font-family: "courier new";">wend</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"></span><br />
<br />
Here is what the resulting output looks.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">phone~last~first~</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">Key number 1 is phone<br /> value = 555-555-1234<br />Key number 2 is last<br /> value = Thumb<br />Key number 3 is first<br /> value = Tom</span><br />
<br />
Notice that the keys do not come out in the order that we put them in. This is typical in dictionary style lookup mechanisms. The ordering of keys is not guaranteed.<br />
<br />Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-44931728958977718342016-07-13T05:36:00.000-07:002016-07-19T10:45:24.039-07:00Dictionary lookup - saving to diskOne advantage of using our single string dictionary lookup technique is that saving to and reading from a disk file is amazingly simple. Just open the file and write the string.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">sub writeDictionary</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> open "dictionary.dat" for output as #writeDict</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> print #writeDict, dictionary$</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> close #writeDict</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">end sub</span><br />
<br />
Reading on the other hand requires a <i>slightly</i> more sophisticated technique. For example, if any of the keys or values have return characters in them then we want to make sure we read the whole file all the way to the end. For this we will use the input$() function.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">sub readDictionary</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> open "dictionary.dat" for input as #readDict</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> length = lof(#readDict)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> dictionary$ = input$(#readDict, length)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> close #readDict</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">end sub</span><br />
<br />
The ability to preserve return characters is useful more for the values than for the keys, which for most applications will probably just be short one or two word names.Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-74038933917490798812016-07-12T06:10:00.000-07:002016-07-12T06:10:21.921-07:00Liberty BASIC on the Rosetta Code siteOne of the members of our community forum posted about some graphics code that he wrote on the Rosetta Code site.<br />
<br />
Here is his post.<br />
<a href="http://libertybasic.conforums.com/index.cgi?board=LB3&action=display&num=1468265910">http://libertybasic.conforums.com/index.cgi?board=LB3&action=display&num=1468265910</a><br />
<br />
I'm glad he posted about it just as a reminder to what a great resource the Rosetta Code site is. There are many, many code samples there to learn from. Check out this link.<br />
<br />
<a href="http://rosettacode.org/wiki/Category:Liberty_BASIC">http://rosettacode.org/wiki/Category:Liberty_BASIC</a><br />
<br />
And, if you'd like to get in on the action there are many Rosetta Code examples which have not yet been implemented in Liberty BASIC. For a list try this link:<br />
<br />
<a href="http://rosettacode.org/wiki/Reports:Tasks_not_implemented_in_Liberty_BASIC">http://rosettacode.org/wiki/Reports:Tasks_not_implemented_in_Liberty_BASIC</a><br />
<br />
These are implemented in other language on the Rosetta Code site so if you'd like to try your hand at writing one or more in Liberty BASIC there are examples to glean inspiration from.Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-64157673180132657462016-07-11T06:08:00.000-07:002016-07-11T06:11:15.983-07:00Dictionary lookup - Garbage collectionIf we need to use our keyed dictionary lookup functions for a purpose where we will change the values for any or all keys the string we save in dictionary$ will get larger each time we set a key and value. This is because the setValueByName subroutine sets a key and value by adding onto the front of the dictionary$ variable but it does not remove any preexisting value for that key. So if for example I set a key of "storeFolder" and a value of "c:\myStoreFolder" and then later I change the value to "c:\myOtherFolder" I will have two different entries for the key "storeFolder". Only the latest value will be returned by the getValue$() function.<br />
<br />
So, how do we fix this? We implement a garbage collector. We can create a subroutine that makes a copy of dictionary$ that only has the latest value for each key.<br />
<br />
Here is a first stab at a garbage collector subroutine.<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">sub collectGarbage</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> pointer = 1</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> while pointer > 0</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> 'get the next key</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> pointer = instr(dictionary$, "~key~", pointer)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if pointer then</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> keyPointer = pointer + 5</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> pointer = instr(dictionary$, "~value~", pointer)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> key$ = mid$(dictionary$, keyPointer, pointer - keyPointer)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> if instr(keyList$, key$) = 0 then</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> value$ = getValue$(key$)</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> newDictionary$ = "~key~" + key$ + "~value~" + value$ + newDictionary$</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> keyList$ = keyList$ + key$</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> end if</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> end if</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> wend</span><br />
<span style="font-family: "courier new" , "courier" , monospace;"> dictionary$ = newDictionary$</span><br />
<span style="font-family: "courier new" , "courier" , monospace;">end sub</span><br />
<br />Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-67368608806887886512016-07-08T06:04:00.000-07:002016-07-08T13:17:01.925-07:00Keyed dictionary lookup in Liberty BASICLiberty BASIC has a way to manage collections of data by using arrays and you look up the information by numeric position. You can do a lot with this but it doesn't let you look up information by name.<br />
<br />
We can provide an easy to use way to do this in Liberty BASIC by using the string functions of Liberty BASIC. By using a single string we can have easy lookup of values by name and also have the ability to store the collection of values in a file and retrieve it simply. In some versions of BASIC this is only useful for small lists of information because of string size limitations of 255. Liberty BASIC permits strings of millions of characters so this is not a problem.<br />
<br />
Here is a very simple demo of the concept just to get us started. In future postings we will explain and enhance the way this works.<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">global dictionary$</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: 'Courier New', Courier, monospace;">call setValueByName "first", "Tom"</span><br />
<span style="font-family: Courier New, Courier, monospace;">call setValueByName "last", "Thumb"</span><br />
<span style="font-family: Courier New, Courier, monospace;">call setValueByName "phone", "555-555-1234"</span><br />
<br />
<span style="font-family: Courier New, Courier, monospace;">print getValue$("last")</span><br />
<span style="font-family: Courier New, Courier, monospace;">print getValue$("blah")</span><br />
<span style="font-family: Courier New, Courier, monospace;">print getValue$("phone")</span><br />
<span style="font-family: Courier New, Courier, monospace;">print getValue$("first")</span><br />
<br />
<span style="font-family: Courier New, Courier, monospace;">sub setValueByName key$, value$</span><br />
<span style="font-family: Courier New, Courier, monospace;"> dictionary$ = "~key~"+key$+"~value~"+value$+dictionary$</span><br />
<span style="font-family: Courier New, Courier, monospace;">end sub</span><br />
<br />
<span style="font-family: Courier New, Courier, monospace;">function getValue$(key$)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> getValue$ = chr$(0)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> keyPosition = instr(dictionary$, "~key~"+key$)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if keyPosition > 0 then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> keyPosition = keyPosition + 5 'skip over key tag</span><br />
<span style="font-family: Courier New, Courier, monospace;"> valuePosition = instr(dictionary$, "~value~", keyPosition)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if valuePosition > 0 then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> valuePosition = valuePosition + 7 'skip over value tag</span><br />
<span style="font-family: Courier New, Courier, monospace;"> endPosition = instr(dictionary$, "~key~", valuePosition)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> if endPosition > 0 then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> getValue$ = mid$(dictionary$, valuePosition, endPosition - valuePosition)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> else</span><br />
<span style="font-family: Courier New, Courier, monospace;"> getValue$ = mid$(dictionary$, valuePosition)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;"> end if</span><br />
<span style="font-family: Courier New, Courier, monospace;">end function</span><br />
<div>
<br /></div>
Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0tag:blogger.com,1999:blog-9257415.post-33621079169233356232016-07-01T05:37:00.000-07:002016-07-01T05:50:49.997-07:00Leveraging the lesson browserLiberty BASIC has a cool feature that many people don't take advantage of. It's called the lesson browser. It allows you to create a collection of different programs in a single file arranged in an outline fashion along with comments for each program.<br />
<br />
This is great for:<br />
<ol>
<li>Creating lessons (yeah)</li>
<li>Sharing ideas with others</li>
<li>Grouping related programs in a project</li>
<li>Tracking the evolution of a program (a kind of versioning)</li>
</ol>
<div>
Here is a screenshot of the lesson browser in action. It is used to provide a tutorial and also example of new features of Liberty BASIC, but it can be used by users to create any collection of programs along with documentation.</div>
<div>
<br /><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig6jDmyzFlHsR5bdfugEjNVMNi4XZkpnPyPCpQdfgAP1yCf1yMMNfu680nGqIliMMTDtG563h7WKbwRRYPiuc-H0x9VqUBuygLI8xQxBFcwfYSgoh6Z-GHav7xbqx5K2IND98K/s1600/Screen+Shot+2016-07-01+at+8.47.28+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="235" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig6jDmyzFlHsR5bdfugEjNVMNi4XZkpnPyPCpQdfgAP1yCf1yMMNfu680nGqIliMMTDtG563h7WKbwRRYPiuc-H0x9VqUBuygLI8xQxBFcwfYSgoh6Z-GHav7xbqx5K2IND98K/s320/Screen+Shot+2016-07-01+at+8.47.28+AM.png" width="320" /></a></div>
<br /></div>
Carl Gundelhttp://www.blogger.com/profile/02824706988216699282noreply@blogger.com0