QCalc is a spreadsheet program with the Q programming language under its hood. It lets you run all Q functions, no strings attached, and you can define your own functions in a script and use these in the spreadsheet, too. As such, it should be useful as an educational tool, or if you simply want to play around with the Q interpreter in a more convenient graphical and interactive environment.

Also note that there's only one spreadsheet and one script per file in the current implementation. But the spreadsheet can get as large as you want and each cell may hold an arbitrarily complex Q value. The user script may import other source files as necessary, using Q's import / include statements, so the single script page doesn't really limit what you can do either.

QCalc is a spreadsheet program with Q as its underlying programming language. The present version is more a replacement frontend to the Q interpreter rather than a full-blown spreadsheet, so some functionality you know from other spreadsheets may still be missing or be implemented in a slightly different way. But if you've ever worked with MS Excel or its OpenOffice and KOffice equivalents, you should feel right at home. The only major difference is that each cell may hold either text, a number or any Q value.

Chapter 2. Using QCalc

If you have ever used another spreadsheet program then the basic paradigm should be familiar and using QCalc should be rather straightforward. In the following we discuss the most important aspects of QCalc's operation, which will hopefully provide you with enough information to get started.

After installing the program, you can simply fire it up using the command qcalc or qcalc mysheet.qcalc. To exit the program, use the Quit option of the File menu or just press Ctrl-Q; you will be warned and get a chance to abort the operation if the current file hasn't be saved yet.

The following screenshot shows QCalc in action:

QCalc is a standard Qt application with menu, toolbar, main area (showing the spreadsheet by default) and a status bar which displays helpful status information like the current cell index and the line number in the script editor. The spreadsheet takes the form of a table with columns numbered A, B, etc., and rows 1, 2, etc. The table is browsed with the usual mouse and keyboard operations.

Online help is available with the F1 key or any of the options in the Help menu. These options invoke the Qt "assistant" program, which is Qt's HTML help browser. (As you're reading the online manual right now, you probably discovered this already.) The full Q language manual is included, too, to assist you on your journey into the "land of Q". Just press Shift-F1 to show the manual in the help browser.

2.1. The Spreadsheet The File menu provides the necessary operations to create new spreadsheets and load, save and print them. QCalc saves its spreadsheets in a text format which is in fact valid Q script syntax, but uses the .qcalc extension by default. (The contents of the spreadsheet are stored as comments at the beginning of the script; it goes without saying that you shouldn't remove or alter these lines if you edit the file with a text editor, unless you know what you are doing.) QCalc also provides some locale support, in that the encoding of a spreadsheet file is recorded in the first line of the file when it is saved. When the file is loaded again, the encoding tag is read and the contents of the file are converted to the current system encoding on the fly. It is also possible to open any plain Q script in QCalc, which then becomes an empty spreadsheet with the given Q source as the user script. (This only works properly if the file actually contains a valid Q script.) As in other spreadsheets, rows are numbered starting at 1, while columns are denoted using the letters A through Z. Beyond the 26th column the indices are denoted AA, AB, ..., BA, BB, etc. In formulas, cell indices are always written with the column letters first. (These are also valid Q variable identifiers, thus you cannot use a global Q variable in formulas if it looks like a cell index.) In difference to other spreadsheets, a table cell in QCalc may contain arbitrary Q values and thus cell values may in fact be complex data structures, not just strings and numbers. It is also possible to populate cells with special GUI elements, including various types of widgets for numerical and symbolic data entry, as well as graphical plots of spreadsheet data using the gnuplot program, see Chapter 3 for details. Each spreadsheet initially starts out with 128x26 cells, i.e. rows 1 thru 128 and columns A thru Z. (This is currently hardcoded in the program, but you can change the default size by editing the qcalc.ui file accordingly.) A spreadsheet grows and shrinks as necessary with certain editing operations (see Section 2.3), but QCalc always keeps it at a minimum size of 128x26. Row and column sizes can be changed by dragging the borders in the row and column headers, and you can also quickly adjust the size by double-clicking on the border. The sizes will be remembered on a per-file basis when the spreadsheet is saved and then reloaded.

2.2. Formulas and Evaluation Q expressions to be evaluated are written in the customary " = expr " format. (Note that the = symbol must be the first character, the formula won't be recognized as such if it is preceded by whitespace). Thus, e.g., if you have the literal values 6 and 7 in cells A1 and B1, and A2 contains " = A1*B2 ", then you will get the value 42 there. The cell will also show a little arrow symbol to indicate that there is a computed value there, so it will actually look like " 42 ". In your formulas you can also use relative and absolute cell references like A1 , B$2 , $C5 or $E$9 just like in any other spreadsheet. These work exactly the same, as far as evaluation is concerned, but behave differently when they are copied or filled (see Section 2.3 below). You can also employ ranges of the form A1:A10 , which are mapped to Q lists (or lists of lists, if they span multiple rows and columns, as in B5:C12 ). You can also do calculations with strings, of course, using Q's string operators and functions, but note that to get an empty string value you'll have to use the formula ' = "" '. That's because the value of an empty cell defaults to the integer 0 (rather than the empty string) in calculations. In fact, this spreadsheet is much more powerful than others in that cells can hold any Q value and you can do calculations with any kind of Q data, including "infinite" values such as streams (lazy lists). And, because of Q's term rewriting heritage, you can do symbolic calculations, too! Also note that if an expression doesn't evaluate because some arguments don't match, this is not an error in Q – the expression is then considered a normal form and will be printed "as is". So, if the computed value in a cell looks "weird", take a second look at the computed formula; you will always find that there's something in there which "doesn't compute", as they say. Actually, this feature is quite useful, as it really shows you where your computation went wrong, instead of just giving you some silly error message. On the other hand, it is an error if an expression doesn't have a value, either because it is not valid Q syntax, or because it raises an exception (e.g., by calling halt or throw ) when evaluated. In the former case, the cell will just show the formula as literal text (without the arrow symbol). The latter kind of error is flagged (quite literally) with a little red flag instead of the arrow symbol, showing the offending formula as the contents of the cell: " = halt ". (Currently QCalc doesn't show you the actual exception raised by an expression, but you can easily find out about these by making judicious use of Q's built-in catch function.) When you enter a new or edit an existing cell value, the evaluation algorithm used by QCalc will only reevaluate the cells affected by this change. Cyclic computations (e.g., if cell A1 is computed using A1 itself, or if there is a cyclic chain of cell dependencies, such as A1=A2+1 and A2=2*A1) are permitted, but are executed in a "depth-first" order which breaks cycles in an apparently random way. The only thing that you can count on in such cases is that if you edit a given cell, then the change will propagate to other cells from there and each dependent cell will be recomputed at most once using the most recent values of all its requisite cells. The entire spreadsheet is reevaluated each time it is loaded, or when you recompile the script of the spreadsheet (see Section 2.4 below). Note that QCalc doesn't limit your spreadsheet to operations which always terminate. If a computation (indicated by the wait cursor) takes longer than expected, or just loops indefinitely, you can abort it with Ctrl-G (this is the only operation active while an evaluation is in progress), and correct the offending spreadsheet cells and/or definitions in the script. In the latter case you can then force a reevaluation of the entire spreadsheet by recompiling the script with F9 (see Section 2.4 below). Also note that all computations are actually executed in a secondary process running your script in a separate instance of the Q interpreter, so it shouldn't be possible to mess up QCalc no matter how badly your script behaves. In the worst case, if your script just "hangs" or "dies", so that QCalc cannot perform further calculations, you should still be able to correct your script in the editor and then just restart it with F9.

2.3. Editing The editing operations provided by QCalc are rather straightforward. You can find these in the Edit menu, as well as the Edit toolbar and the context menu which pops up when you right-click on a table cell. There are also many useful keyboard and mouse shortcuts. You can browse through your spreadsheet with the mouse or the cursor keys, including the Tab and Backtab keys which traverse to the next and previous table cell (in row-major order), respectively. F3 or Shift-F3 edits a cell (the former edits the cell "in-place", while the latter invokes a separate multiline editor which is often more convenient for complicated formulas), Esc aborts the edit (reverting the cell to its previous value), and F2 or Return stores the edited value (and does any necessary computations). You can force reevaluation of a cell by pressing F2 while the cell is selected, and a double click opens a cell for editing. You can also just start typing when a cell is selected, to overwrite its current value. Cell indices and formulas are shown in the status line when you click on them. NOTE: Browsing the table and selecting ranges of cells with the mouse or the keyboard can be hard to do if the cells contain editable GUI elements like comboboxes and spinboxes (see Section 3.3), since these will grab the focus when they are selected. As a remedy, if you are not currently editing a cell, the Esc key allows you to switch the table from the default mode of operation to a special "browse" mode which is indicated by a tiny lock symbol in the status line. While the table is in browse mode, editing operations on ranges of cells still work normally, but GUI elements are not activated when selected any more. This makes it much easier to browse the table and make selections with the mouse or the cursor keys. To leave browse mode, either just press Esc again, or double-click on a cell or press F3 to open a cell for editing. Rectangular ranges of spreadsheet cells can be selected by sweeping the mouse over them as usual, or by using the cursor keys while holding down the Shift key. You can also click a row or column header to select the entire row or column. Selected ranges of cells can be deleted, cut, copied and pasted as usual. Using cut/copy and paste you can also transfer ranges between different instances of QCalc. Moreover, QCalc performs automatic adjustment of relative column and row indices in formulas. Thus, if you copy a cell containing the formula " = foo A1 " to a position at an offset of, say, 2 rows and 3 columns from the original position, it will become " = foo D3 ". As usual, you can use the $ symbol to indicate absolute row or column indices (or both) which will not be adjusted. The Paste operation always copies formulas for computed cells, but there is also a second "Paste values" operation to just copy the literal cell contents (without the formulas). QCalc can also exchange data with other programs, using the customary textual "tab-separated values" format to store the selection in the clipboard, which can readily be pasted into almost any other application, including text editors and other spreadsheet programs. On X11, the global mouse selection is also supported; just select a range of cells, and you can paste their contents in tab-separated format into any other application with the middle mouse button. There's also a special Fill operation which basically works like dragging the little fill handle in other spreadsheets to copy a value or formula to adjacent cells. In fact, this operation is even more flexible than the fill handle, since it allows you to fill both rows and columns in a single step. To use this, select the desired target range, with the value to be copied in the "principal" (upper-left) cell of the selected range, and then just push the Fill button (the one with the magic wand symbol on it), or press Ctrl-L. This will copy the formula in the principal cell to the adjacent cells, adjusting it across the range as usual. The same operation also allows you to fill a range of cells with arithmetic sequences. For this purpose, the principal cell value is the starting value of the sequence, and the cells immediately below and to the right of the principal cell (more precisely, the differences between these values and the principal cell value) determine the increment in the vertical and horizontal direction, respectively. If one or both of the adjacent cells are empty or non-numeric then the corresponding increment defaults to 0 (meaning that the principal value will just be copied). Thus, when the operation has finished, each row or column will be an arithmetic sequence for the indicated horizontal or vertical increment, respectively. (This sounds more complicated than it actually is. Just try it out and see what happens.) The Merge cells option (F6) in the Edit menu allows you to merge adjacent cells into one bigger cell which may span multiple rows and columns; the Dissociate cells (Shift-F6) option splits them up into their constituents again. You can also insert and delete entire rows and columns by selecting a cell (a single cell will do, although you can also select a range, in which case the upper left cell of the range determines where the operation is to be performed) and choose the corresponding option. The corresponding keyboard shortcuts are F7 and Shift-F7 to insert and delete a row, and F8 and Shift-F8 to insert and delete a column, respectively. Each of the these operations only inserts or deletes a single row or column, so you have to invoke the command repeatedly if you want more. Also note that the other editing operations will enlarge the table if needed, e.g., when you paste a range of cells near the edges of the spreadsheet. Thus it is not necessary to explicitly insert table rows and columns in such cases. QCalc also has an unlimited undo/redo facility, so if you mess up your spreadsheet you can always go back and forth in time as needed. These operations also adjust the table size as needed. They may also shrink the table if there is unused extra space; this also happens when you load a spreadsheet from a file. However, as already mentioned, QCalc always keeps the spreadsheet at a minimum table size of 128x26.

2.4. The Script You get to the script page by switching to the corresponding tab located right below the menu and toolbar, or by pressing F11 which toggles between the spreadsheet and the script view. After selecting the script view you see the following: In the upper pane of the script page, there is a full-featured text editor with syntax highlighting for Q scripts. In the editor you can enter any Q script, which is submitted to the Q compiler when you invoke the Compile operation (F9). The script can also be empty if your spreadsheet only uses the built-in and prelude types and functions of the Q language. Or it may just consist of the appropriate import declarations for the additional modules containing the needed operations. But in most cases it will just include any additional definitions required for the operation of your spreadsheet. If there are any errors or warning messages during compilation of the script, they will be shown in the lower "log" pane of the script page. The log pane is also used to show output produced by Q's I/O operations like puts or printf . But note that the log is just that, a log of everything that is printed either by the Q compiler or the operations in your spreadsheet; it's not an interactive kind of terminal window, so it isn't possible to interact with the interpreter or enter any input to operations like gets and scanf there. Also note that the log is cleared automatically whenever you recompile your script or load a new spreadsheet. You must correct all errors in your script before you can evaluate anything. As soon as your script is error-free, after pressing F9 the entire spreadsheet will be reevaluated, using the definitions from your script. For instance, if you want to use a function square in your spreadsheet, which isn't provided by the Q library, you can define it yourself as follows: square X = X*X; Enter this definition in the script editor and press F9. Voila, the new function is now available and you can use it in your spreadsheet just like any other function. E.g., you can now type the formula " = square 9 " into a cell and it will evaluate to 81. Some special support operations for use in QCalc scripts can be found in the calclib.q module which is to be installed on the Q path. These are described in some detail in Chapter 3. The script editor has two additional editing operations provided for your convenience, the Find/Replace dialog (Ctrl-F) which lets you, well, find text and replace it, and the "Goto line" (F5) operation to locate the given line number, which comes in handy to find the lines listed in compiler error messages. The Find/Replace dialog looks as follows: Just enter the text to be searched and, if applicable, the replacement text in the corresponding fields and hit the Next button to search for the first occurrence behind the cursor, or press the Return key. Keep on pushing Next or Return to search for further occurrences, or push Replace to perform a replacement and search for the next occurrence. Backward searches and replacements work analogously, using the Prev button instead of Next. (You can switch the search direction at any time.) There are also various options which determine whether the search is case-sensitive and/or for whole words only, and whether to preserve the case of replaced text (which works as in Emacs). NOTE: With the Qt3 highlighting engine, the syntax highlighting of the script editor can slow things down quite a bit with large scripts. As a remedy, if the highlighting makes the editor unresponsive and sluggish, you can disable it with the Syntax highlighting toggle (Ctrl-H).

2.5. View Options There are a few options which allow you to change the visual appearance of the spreadsheet and the script display. These settings are global and are remembered across invocations of the program. You can change the font of the spreadsheet or the text editor by selecting the corresponding tab and invoking the Choose font operation. Fixed width fonts seem to work best for most purposes, although YMMV. The configured fonts are also used for printing, see below.

The Zoom in and Zoom out ( Ctrl-+ and Ctrl-- ) commands allow you to quickly change the font size on either the sheet or the script page.

The Increase precision and Decrease precision ( Alt-+ and Alt-- ) commands let you to change the precision of floating point values in computed cells. (This affects the display of floating point values only; internally, these values are always stored at full precision.)

As already mentioned, the Syntax highlighting toggle (Ctrl-H) switches syntax highlighting in the script editor on and off.