Since before Doors CS 6.0 was released in 2007, I have thrown around the idea of including Doors CS-specific BASIC libraries in the shell. In the past I have always ended up rejecting the idea, either because of a lack of space in the app, or more often, because I was concerned about breaking the compability for which I had always striven by making the DCS BASIC header compatible with every other parser. With the addition of a third page to Doors CS, as well as the inclusion of libraries to support XLib, Celtc III, PicArc, and Omnicalc, I have decided that offering additional functionality to BASIC programmers who want it is more important than ensuring wide compatibility of Doors CS program.
Of course, programmers are encouraged to make programs that work with or with the Doors CS libraries; just as real(0) and Det([[1]]) can be used to detect if XLib or Celtic III is installed, Doors CS has a token detection sequence. If no library is installed, det([[42]]) will return 42. If Celtic III is installed, it will return 0. If Doors CS is installed and providing both Celtic III and Doors CS libraries, it will return the value 1337. So far, thirteen main Doors CS libraries have been designed (but please feel free to suggest changes and additions!); all can be accessed using the sum() token. Just as with Celtic's use of the det() token, sum() will continue to function normally if used with a list as the first argument. If the first argument is instead an integer, Doors CS will intercept it, and perform one of the following planned functions:
:: sum(0) - Determine the length of a string of tokens in variable-width font
:: sum(1) - Scan in specified direction along the graphscreen from a starting point until a differently-valued pixel is encountered
:: sum(2) - Copy the homescreen to the graph buffer
:: sum(3) - List all present Pic 1-255 variables, including their archive status
:: sum(4) - Archive or unarchive a Pic 1-255 variable
:: sum(5) - Return version of installed DCSB Lib
:: sum(6) - Simple GUI mouse, taking starting coords and returning ending coords
:: sum(7) - Push item onto GUI stack. 25 subfunctions.
:: sum(8) - Pop item(s) off GUI stack
:: sum(9) - Open GUI stack.
:: sum(10) - Close GUI stack.
:: sum(11) - Render GUI without invoking mouse.
:: sum(12) - Render GUI and invoke mouse.
:: sum(13) - More graphical scrolling Menu() alternative.
All the libraries except sum(7), sum(12), and sum(13) have been implemented. Continue reading at the discuss link for details on these libraries.
The images below demonstrate some of the already-implemented features
(0) Get string width in var-width font: sum(0,{string})
Given a string, find its width if written in variable-width or graphscreen font
(1) Scan for pixel: sum(1,{X},{Y},{dir})
From starting location (X,Y), scan along the LCD until an edge or a pixel UNLIKE the value of the starting pixel is encountered (dark to light, or light to dark). If a screen edge is reached, behaves as if the color changed. (dir: 1=up, 2=down, 3=left, 4=right)
(2) Render homescreen on graphscreen: sum(2,{update})
Draw 128 characters from the homescreen text buffer to the graph buffer. If update=1, also copy to the LCD.
(3) Used pic vars: sum(3)
Returns an N-element list of the numbers of the Pic variables on the calculator (Pic0 = 10). For example, {1,3,10,24} means that Pic 1, Pic 3, Pic 0, and Pic 24 (an extended Pic) are on the calculator.
(4) Arc/Unarc Pic: sum(4,{N},{state})
Unarchive Pic N if state=0, or archive it if state=1. If it is already in the desired state, do nothing.
(5) Return DCS Lib Version: sum(5)
Will return a number indicating what library is being presented to the program, which should indicate what routines are available. This will be set up to return a specific value when Doors CS is _not_ installed, just like real(0).
(6) DCS Mouse: sum(6,{X},{Y})
Run the DCS GUI Mouse starting at {X},{Y}, with acceleration and the user's custom cursor. Will return a list {X,Y,click}, where (X,Y) is the final cursor location, and click = 1 or 2 for left- or right-clicking. This routine will leave the gbuf the way it found it (as well as the GUI stack)
(7) Push GUI Stack: sum(7,{type},{more args...}
This will probably be the most complex type. The following {type} values will take the following arguments:
:: 0 :: GUIRNull: {255} is the only argument. If you wish the item to be transparent, use {254} instead.
:: 1 :: GUIRLargeWin: {icon (10 hex chars)},{title string}
:: 2 :: GUIRSmallWin: {top-left X (0-15)},{top-left Y (0-15)}, {icon (10 hex chars)},{titlestring}
:: 3 :: GUIRFullScreenImg: {# of Pic variable containing img}
:: 4 :: GUIRText: {X},{Y},{0},{string}
:: 5 :: GUIRWinButtons: {128 + 64 + 32}. 128 if a minimize button should be shown, 64 if a maximize button should be shown, 32 if a close button should be shown. eg, 160 for just minimize and close. 32 for just close. 64 for just maximize. 192 for all three.
:: 6 :: GUIRWrappedText: {X},{Y},{width in pixels},{0},{string}
:: 7 :: GUIRButtonText: {X},{Y},{string}
:: 8 :: GUIRButtonImg: {X},{Y},{image width in bytes},{button width in pixels},{image hex, 10*image width characters long}
:: 9 :: GUIRTextLineIn: {X},{Y},{width in pixels},{maximum chars},{initial string}
:: 10 :: GUIRRadio: {X},{Y},{group ID},{0 or 1},{string}
:: 11 :: GUIRCheckBox: {X},{Y},{group ID},{0 or 1},{string}
:: 12 :: GUIRByteInt: {X},{Y},{initial},{min},{max}
:: 13 :: GUIRWordInt: {X},{Y},{initial},{min},{max}
:: 14 :: GUIRHotspot: {X},{Y},{width},{height}
:: 15 :: GUIRTextMultiline: {X},{Y},{rows},{px width},{string}
:: 16 :: GUIRSprite: {X},{Y},{height (8 px wide is assumed)},{2*height hex chars}
:: 17 :: GUIRLargeSprite: {X},{Y},{width in bytes},{height in px},{height*width*2 hex chars}
:: 18 :: GUIRPassIn: {X},{Y},{width in px},{max chars},{initial string}
:: 19 :: GUIRScrollVert: {X},{Y},{height in px},{ID},{inc/dec per click}, {min val},{max val},{current}
:: 20 :: GUIRScrollHoriz: {X},{Y},{width in px},{ID},{inc/dec per click}, {min val},{max val},{current}
:: 21 :: GUIRBorder: {X},{Y},{width},{height},{color}
:: 22 :: GUIRRect: {X},{Y},{width},{height},{color}
:: 23 :: THERE IS NO 23
:: 24 :: GUIRMouseCursor: {X1*256+Y1},{X2*256+Y2},{16-char mask},{16-char cursor}
(8) Pop GUI Stack Items: sum(8,{number to pop})
Self-explanatory
(9) Open GUI Stack: sum(9)
Initialize the GUI Stack
(10) Close GUI Stack: sum(10)
Shut down the GUI stack
(11) Render GUI Stack: token(11)
Just render, don't call the mouse
(12) GUIMouse: token(12)
Render, and start the mouse. This will return a whole mass of stuff, including a list of {X,Y,num}, where num is the index of the element that made mouse execution stop, and a String (maybe Str0?) that contains packed outputs from text input boxes, number input boxes, radio buttons, and checkboxes.
(13) Scrolling menu: token(13,"TITLE","box-delimited item list","packed label list")
Because of certain limitations in passing strings to parserhook'd functions, the list of items is a single string delimited by the plot box character. The list of labels for Goto'ing are packed, such as one-character labels are represented as [space][char]. For a three-item menu that has the option to Goto Lbl AA, Lbl H, or label QQ, the list would look like: "AA HQQ". This routine creates a small window with the menu items and a scrollbar, allows scrolling, and does the requested Goto. It however does NOT invoke the GUI Mouse.
Of course, programmers are encouraged to make programs that work with or with the Doors CS libraries; just as real(0) and Det([[1]]) can be used to detect if XLib or Celtic III is installed, Doors CS has a token detection sequence. If no library is installed, det([[42]]) will return 42. If Celtic III is installed, it will return 0. If Doors CS is installed and providing both Celtic III and Doors CS libraries, it will return the value 1337. So far, thirteen main Doors CS libraries have been designed (but please feel free to suggest changes and additions!); all can be accessed using the sum() token. Just as with Celtic's use of the det() token, sum() will continue to function normally if used with a list as the first argument. If the first argument is instead an integer, Doors CS will intercept it, and perform one of the following planned functions:
:: sum(0) - Determine the length of a string of tokens in variable-width font
:: sum(1) - Scan in specified direction along the graphscreen from a starting point until a differently-valued pixel is encountered
:: sum(2) - Copy the homescreen to the graph buffer
:: sum(3) - List all present Pic 1-255 variables, including their archive status
:: sum(4) - Archive or unarchive a Pic 1-255 variable
:: sum(5) - Return version of installed DCSB Lib
:: sum(6) - Simple GUI mouse, taking starting coords and returning ending coords
:: sum(7) - Push item onto GUI stack. 25 subfunctions.
:: sum(8) - Pop item(s) off GUI stack
:: sum(9) - Open GUI stack.
:: sum(10) - Close GUI stack.
:: sum(11) - Render GUI without invoking mouse.
:: sum(12) - Render GUI and invoke mouse.
:: sum(13) - More graphical scrolling Menu() alternative.
All the libraries except sum(7), sum(12), and sum(13) have been implemented. Continue reading at the discuss link for details on these libraries.
The images below demonstrate some of the already-implemented features
(0) Get string width in var-width font: sum(0,{string})
Given a string, find its width if written in variable-width or graphscreen font
(1) Scan for pixel: sum(1,{X},{Y},{dir})
From starting location (X,Y), scan along the LCD until an edge or a pixel UNLIKE the value of the starting pixel is encountered (dark to light, or light to dark). If a screen edge is reached, behaves as if the color changed. (dir: 1=up, 2=down, 3=left, 4=right)
(2) Render homescreen on graphscreen: sum(2,{update})
Draw 128 characters from the homescreen text buffer to the graph buffer. If update=1, also copy to the LCD.
(3) Used pic vars: sum(3)
Returns an N-element list of the numbers of the Pic variables on the calculator (Pic0 = 10). For example, {1,3,10,24} means that Pic 1, Pic 3, Pic 0, and Pic 24 (an extended Pic) are on the calculator.
(4) Arc/Unarc Pic: sum(4,{N},{state})
Unarchive Pic N if state=0, or archive it if state=1. If it is already in the desired state, do nothing.
(5) Return DCS Lib Version: sum(5)
Will return a number indicating what library is being presented to the program, which should indicate what routines are available. This will be set up to return a specific value when Doors CS is _not_ installed, just like real(0).
(6) DCS Mouse: sum(6,{X},{Y})
Run the DCS GUI Mouse starting at {X},{Y}, with acceleration and the user's custom cursor. Will return a list {X,Y,click}, where (X,Y) is the final cursor location, and click = 1 or 2 for left- or right-clicking. This routine will leave the gbuf the way it found it (as well as the GUI stack)
(7) Push GUI Stack: sum(7,{type},{more args...}
This will probably be the most complex type. The following {type} values will take the following arguments:
:: 0 :: GUIRNull: {255} is the only argument. If you wish the item to be transparent, use {254} instead.
:: 1 :: GUIRLargeWin: {icon (10 hex chars)},{title string}
:: 2 :: GUIRSmallWin: {top-left X (0-15)},{top-left Y (0-15)}, {icon (10 hex chars)},{titlestring}
:: 3 :: GUIRFullScreenImg: {# of Pic variable containing img}
:: 4 :: GUIRText: {X},{Y},{0},{string}
:: 5 :: GUIRWinButtons: {128 + 64 + 32}. 128 if a minimize button should be shown, 64 if a maximize button should be shown, 32 if a close button should be shown. eg, 160 for just minimize and close. 32 for just close. 64 for just maximize. 192 for all three.
:: 6 :: GUIRWrappedText: {X},{Y},{width in pixels},{0},{string}
:: 7 :: GUIRButtonText: {X},{Y},{string}
:: 8 :: GUIRButtonImg: {X},{Y},{image width in bytes},{button width in pixels},{image hex, 10*image width characters long}
:: 9 :: GUIRTextLineIn: {X},{Y},{width in pixels},{maximum chars},{initial string}
:: 10 :: GUIRRadio: {X},{Y},{group ID},{0 or 1},{string}
:: 11 :: GUIRCheckBox: {X},{Y},{group ID},{0 or 1},{string}
:: 12 :: GUIRByteInt: {X},{Y},{initial},{min},{max}
:: 13 :: GUIRWordInt: {X},{Y},{initial},{min},{max}
:: 14 :: GUIRHotspot: {X},{Y},{width},{height}
:: 15 :: GUIRTextMultiline: {X},{Y},{rows},{px width},{string}
:: 16 :: GUIRSprite: {X},{Y},{height (8 px wide is assumed)},{2*height hex chars}
:: 17 :: GUIRLargeSprite: {X},{Y},{width in bytes},{height in px},{height*width*2 hex chars}
:: 18 :: GUIRPassIn: {X},{Y},{width in px},{max chars},{initial string}
:: 19 :: GUIRScrollVert: {X},{Y},{height in px},{ID},{inc/dec per click}, {min val},{max val},{current}
:: 20 :: GUIRScrollHoriz: {X},{Y},{width in px},{ID},{inc/dec per click}, {min val},{max val},{current}
:: 21 :: GUIRBorder: {X},{Y},{width},{height},{color}
:: 22 :: GUIRRect: {X},{Y},{width},{height},{color}
:: 23 :: THERE IS NO 23
:: 24 :: GUIRMouseCursor: {X1*256+Y1},{X2*256+Y2},{16-char mask},{16-char cursor}
(8) Pop GUI Stack Items: sum(8,{number to pop})
Self-explanatory
(9) Open GUI Stack: sum(9)
Initialize the GUI Stack
(10) Close GUI Stack: sum(10)
Shut down the GUI stack
(11) Render GUI Stack: token(11)
Just render, don't call the mouse
(12) GUIMouse: token(12)
Render, and start the mouse. This will return a whole mass of stuff, including a list of {X,Y,num}, where num is the index of the element that made mouse execution stop, and a String (maybe Str0?) that contains packed outputs from text input boxes, number input boxes, radio buttons, and checkboxes.
(13) Scrolling menu: token(13,"TITLE","box-delimited item list","packed label list")
Because of certain limitations in passing strings to parserhook'd functions, the list of items is a single string delimited by the plot box character. The list of labels for Goto'ing are packed, such as one-character labels are represented as [space][char]. For a three-item menu that has the option to Goto Lbl AA, Lbl H, or label QQ, the list would look like: "AA HQQ". This routine creates a small window with the menu items and a scrollbar, allows scrolling, and does the requested Goto. It however does NOT invoke the GUI Mouse.