row_heights (#77)

Implements row heights and a command-line option `-F nn` for fteapot to set the general font size.

Also improves documentation and uniformizes key bindings somewhat between teapot and fteapot.

Resolves #57.

Co-authored-by: Glen Whitney <glen@studioinfinity.org>
Reviewed-on: #77
This commit is contained in:
Glen Whitney 2023-04-09 05:41:50 +00:00
parent 118374c46e
commit 0ca9d0176b
12 changed files with 588 additions and 167 deletions

6
NEWS
View File

@ -11,19 +11,20 @@ o Comparison operators return bool rather than int (Note this can be a breaking
change; you may need to wrap comparisons in int() if you are using the result change; you may need to wrap comparisons in int() if you are using the result
in a numerical computation.) in a numerical computation.)
o Foreground and background color style attributes for cells. o Foreground and background color style attributes for cells.
o Variable row height for cells.
o Addition of a find() macro to search for a cell satisfying a condition. o Addition of a find() macro to search for a cell satisfying a condition.
o Addition of an is(VALUE, TYPE, TYPE,...) predicate o Addition of an is(VALUE, TYPE, TYPE,...) predicate
o Addition of functions for unit displacements in the six cardinal directions o Addition of functions for unit displacements in the six cardinal directions
(left, right, up, down, above, below) (left, right, up, down, above, below)
o TPA is now the default file format o TPA is now the default file format
o Addition of hexact float format, which allow for exact round trips to ASCII o Addition of hexact float format, which allows for exact round trips to ASCII
o New token type: funcall (which basically amounts to an expression). This o New token type: funcall (which basically amounts to an expression). This
allows parsed rather than unparsed expressions to be stored in cells, and allows parsed rather than unparsed expressions to be stored in cells, and
allows macros which receive their arguments unevaluated. allows macros which receive their arguments unevaluated.
o sum(), min(), and max() can now operate over their list of arguments as well o sum(), min(), and max() can now operate over their list of arguments as well
as over a block. as over a block.
o Added floor(), ceil(), trunc(), and round() functions for finding integers o Added floor(), ceil(), trunc(), and round() functions for finding integers
associated with doubles, eiminating (note possible breaking change) the associated with doubles, eliminating (note possible breaking change) the
int conversion with two rounding directions. int conversion with two rounding directions.
o Precedence of unary "-" made lower than exponentiation "^" to match Python; o Precedence of unary "-" made lower than exponentiation "^" to match Python;
note possible breaking change. note possible breaking change.
@ -34,6 +35,7 @@ o Fill With operation for quickly filling the selected block with a single cell.
o Additional arithmetic operations on locations. o Additional arithmetic operations on locations.
o Documentation better aligned with current behavior. o Documentation better aligned with current behavior.
o Additional key commands for clocking/resetting the sheet. o Additional key commands for clocking/resetting the sheet.
o New -F command line argument to set the overall font size for fteapot.
Bug fixes: Bug fixes:
o Occasional early coredumps of teapot have been eliminated. o Occasional early coredumps of teapot have been eliminated.

View File

@ -1144,7 +1144,7 @@ Up
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
[+] +
\end_layout \end_layout
\end_inset \end_inset
@ -1264,7 +1264,7 @@ To last column
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
[<] <
\end_layout \end_layout
\end_inset \end_inset
@ -1293,7 +1293,7 @@ To row 0
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
[>] >
\end_layout \end_layout
\end_inset \end_inset
@ -1322,7 +1322,7 @@ To last row
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
[_ (Underscore)] _ (Underscore)
\end_layout \end_layout
\end_inset \end_inset
@ -1351,7 +1351,7 @@ To Layer 0
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
[*] *
\end_layout \end_layout
\end_inset \end_inset
@ -1371,7 +1371,7 @@ To last layer
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
{Ctrl-Right}
\end_layout \end_layout
\end_inset \end_inset
@ -1400,7 +1400,7 @@ Jump one page right
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
{Ctrl-Left}
\end_layout \end_layout
\end_inset \end_inset
@ -1550,7 +1550,7 @@ status open
\begin_layout Plain Layout \begin_layout Plain Layout
\begin_inset Tabular \begin_inset Tabular
<lyxtabular version="3" rows="14" columns="3"> <lyxtabular version="3" rows="15" columns="3">
<features tabularvalignment="middle"> <features tabularvalignment="middle">
<column alignment="left" valignment="top" width="5cm"> <column alignment="left" valignment="top" width="5cm">
<column alignment="left" valignment="top"> <column alignment="left" valignment="top">
@ -1620,7 +1620,7 @@ Operation
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
F10 [F10] {Menu bar always shown}
\end_layout \end_layout
\end_inset \end_inset
@ -1802,6 +1802,35 @@ Activate File menu
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none"> <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout
{Meta-B}
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Activate Block menu
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
{Meta-V} {Meta-V}
\end_layout \end_layout
@ -1848,11 +1877,11 @@ Activate fOrmat menu
</cell> </cell>
</row> </row>
<row> <row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none"> <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
F1
\end_layout \end_layout
\end_inset \end_inset
@ -1861,7 +1890,7 @@ Activate fOrmat menu
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
{Meta-H}
\end_layout \end_layout
\end_inset \end_inset
@ -1870,7 +1899,7 @@ Activate fOrmat menu
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
Activate Help menu Show help
\end_layout \end_layout
\end_inset \end_inset
@ -1910,7 +1939,7 @@ Redraw screen
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
{Esc}
\end_layout \end_layout
\end_inset \end_inset
@ -1919,7 +1948,7 @@ Redraw screen
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
[Ctrl-C] [Ctrl-G] {Esc} [Ctrl-C] [Ctrl-G]
\end_layout \end_layout
\end_inset \end_inset
@ -2002,7 +2031,7 @@ status open
\begin_layout Plain Layout \begin_layout Plain Layout
\begin_inset Tabular \begin_inset Tabular
<lyxtabular version="3" rows="26" columns="3"> <lyxtabular version="3" rows="29" columns="3">
<features tabularvalignment="middle"> <features tabularvalignment="middle">
<column alignment="left" valignment="top" width="5cm"> <column alignment="left" valignment="top" width="5cm">
<column alignment="left" valignment="top"> <column alignment="left" valignment="top">
@ -2430,7 +2459,7 @@ Set cell label
</cell> </cell>
</row> </row>
<row> <row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none"> <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
@ -2443,7 +2472,7 @@ Set cell label
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
{Meta-B} {Ctrl-D}
\end_layout \end_layout
\end_inset \end_inset
@ -2452,7 +2481,7 @@ Set cell label
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
Toggle cell/block bold Toggle cell/block dim
\end_layout \end_layout
\end_inset \end_inset
@ -2472,7 +2501,65 @@ Toggle cell/block bold
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
{Meta-U} {Ctrl-B}
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Toggle cell/block bold
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
{Ctrl-I}
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Toggle cell/block italic
\end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="left" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
{Ctrl-U}
\end_layout \end_layout
\end_inset \end_inset
@ -2629,6 +2716,35 @@ Set cell/block precision
Set column width Set column width
\end_layout \end_layout
\end_inset
</cell>
</row>
<row>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
{Meta-H}
\end_layout
\end_inset
</cell>
<cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
\begin_inset Text
\begin_layout Plain Layout
Set row height
\end_layout
\end_inset \end_inset
</cell> </cell>
</row> </row>
@ -2753,7 +2869,7 @@ Reset sheet
\begin_inset Text \begin_inset Text
\begin_layout Plain Layout \begin_layout Plain Layout
F9, {Shift-Tab} F8, F9, {Shift-Tab}
\end_layout \end_layout
\end_inset \end_inset
@ -3452,7 +3568,7 @@ ignored.
\end_layout \end_layout
\begin_layout Standard \begin_layout Standard
In addition, each column has a width. In addition, each column has a width and each row has a height.
\end_layout \end_layout
\begin_layout Subsubsection \begin_layout Subsubsection
@ -3503,6 +3619,39 @@ The column width only affects the screen display, not the formatting of
It is intended to let you make better usage of the screen for more overview. It is intended to let you make better usage of the screen for more overview.
If the width is too small to display the cell value, a placeholder will If the width is too small to display the cell value, a placeholder will
be displayed. be displayed.
The column width is measured in
\begin_inset Quotes eld
\end_inset
characters,
\begin_inset Quotes erd
\end_inset
which are exact in the console and correspond to an arbitrary notional
character width in the graphical version, where the actual number of characters
that fit in a cell of a given width will depend on the font and size.
\end_layout
\begin_layout Subsubsection
Row Height
\end_layout
\begin_layout Standard
Similar comments apply to the row height as to the column width.
An important difference is that row heights are expressed in
\begin_inset Quotes eld
\end_inset
twelfths of a character.
\begin_inset Quotes erd
\end_inset
This means that in the console version, all row heights upt to 23 are displayed
as a single-character-high row; heights 24 to 35 are shown as two characters
high; and so on.
In the graphical version, of course, the actual row height is proportional
to the specified value, with a height of 12 able to display one full-height
character.
\end_layout \end_layout

View File

@ -39,9 +39,15 @@ endif ()
find_package(FLTK) find_package(FLTK)
if (FLTK_FOUND) if (FLTK_FOUND)
find_program(PYTHON python3 python)
fltk_wrap_ui(fteapot fteapot.fl) fltk_wrap_ui(fteapot fteapot.fl)
include_directories(${FLTK_INCLUDE_DIR}) include_directories(${FLTK_INCLUDE_DIR})
add_executable(fteapot WIN32 tpt_choose.cxx ${fteapot_FLTK_UI_SRCS}) add_executable(fteapot WIN32 tpt_choose.cxx ${CMAKE_CURRENT_BINARY_DIR}/fteapot.h ${CMAKE_CURRENT_BINARY_DIR}/fteapot_interpolated.cxx)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/fteapot_interpolated.cxx
COMMAND ${PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/tools/interpolate.py ${CMAKE_CURRENT_SOURCE_DIR}/fteapot.fl ${CMAKE_CURRENT_BINARY_DIR}/fteapot.cxx
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/fteapot.cxx ${CMAKE_CURRENT_SOURCE_DIR}/tools/interpolate.py
)
target_compile_options(fteapot PRIVATE -Wno-shadow -Wno-conversion -Wno-sign-conversion) target_compile_options(fteapot PRIVATE -Wno-shadow -Wno-conversion -Wno-sign-conversion)
set(fteapot_DEB_DEPENDS ", libstdc++6 (>= 4.1.1), libfltk1.3") set(fteapot_DEB_DEPENDS ", libstdc++6 (>= 4.1.1), libfltk1.3")
if (ENABLE_HELP) if (ENABLE_HELP)

View File

@ -3,8 +3,17 @@
#include <stdlib.h> #include <stdlib.h>
/* default width of a column */ /* default width of a column (in "characters") */
#define DEF_COLUMNWIDTH 12 #define DEF_COLUMNWIDTH 12
/* The number of vertical slices to divide a row into.
Note that only integer multiples of this have any effect
in console mode, but fteapot can save and respect non-
integer multiples of this value */
#define ROWHEIGHT_DENOMINATOR 12
/* default height of a row, in units of ROWHEIGHT_DENOMINATOR,
i.e. these should be equal to make the default height be one.
*/
#define DEF_ROWHEIGHT 12
/* default precision of a printed value */ /* default precision of a printed value */
/* Since the default format now counts significant figures /* Since the default format now counts significant figures

View File

@ -39,6 +39,7 @@ unsigned int batchln=0;
PrecisionLevel def_precision = DEF_PRECISION; PrecisionLevel def_precision = DEF_PRECISION;
StringFormat quote = DIRECT_STRING; StringFormat quote = DIRECT_STRING;
bool header = true; bool header = true;
int fontsize = 14;
bool always_redraw = false; bool always_redraw = false;
int debug_level = 0; int debug_level = 0;
static bool usexdr = false; static bool usexdr = false;
@ -67,13 +68,13 @@ void moveto(Sheet *sheet, CoordT x, CoordT y, CoordT z)
need_redraw = true; need_redraw = true;
sheet->offy = (sheet->cur[Y] > 0) ? sheet->cur[Y]-1 : 0; sheet->offy = (sheet->cur[Y] > 0) ? sheet->cur[Y]-1 : 0;
} }
if (sheet->cur[X] >= sheet->offx + sheet->maxx) { if (sheet->cur[X] >= sheet->offx + (CoordT)sheet->maxx) {
need_redraw = true; need_redraw = true;
sheet->offx = sheet->cur[X] - sheet->maxx + 2; sheet->offx = sheet->cur[X] - (CoordT)sheet->maxx + 2;
} }
if (sheet->cur[Y] >= sheet->offy + sheet->maxy) { if (sheet->cur[Y] >= sheet->offy + (CoordT)sheet->maxy) {
need_redraw = true; need_redraw = true;
sheet->offy = sheet->cur[Y] - sheet->maxy + 2; sheet->offy = sheet->cur[Y] - (CoordT)sheet->maxy + 2;
} }
if (need_redraw) redraw_sheet(sheet); if (need_redraw) redraw_sheet(sheet);
else if (need_cell) redraw_cell(sheet, sheet->cur); else if (need_cell) redraw_cell(sheet, sheet->cur);
@ -312,6 +313,23 @@ static int do_columnwidth(Sheet *cursheet)
} }
/*}}}*/ /*}}}*/
/* do_rowheight -- set the row height */ /*{{{*/
static int do_rowheight(Sheet *cursheet)
{
do_mark(cursheet, GET_MARK_CUR);
int n = (int)rowheight(cursheet, cursheet->mark1[Y], cursheet->mark1[Z]);
do {
int c = line_numedit(&n, _("Row height:"));
if (c < 0) return c;
} while (n <= 0);
RowHgtT rh = (RowHgtT)n;
for (int y = cursheet->mark1[Y]; y <= cursheet->mark2[Y]; ++y)
for (int z = cursheet->mark1[Z]; z <= cursheet->mark2[Z]; ++z)
setheight(cursheet, y, z, rh);
return -1;
}
/*}}}*/
/* do_attribute -- set cell attributes */ /*{{{*/ /* do_attribute -- set cell attributes */ /*{{{*/
static void do_attribute(Sheet *cursheet, Key action) static void do_attribute(Sheet *cursheet, Key action)
{ {
@ -1329,6 +1347,7 @@ int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly)
{ {
case K_GOTO: do_goto(cursheet, (const char *)0); break; case K_GOTO: do_goto(cursheet, (const char *)0); break;
case K_COLWIDTH: do_columnwidth(cursheet); break; case K_COLWIDTH: do_columnwidth(cursheet); break;
case K_ROWHEIGHT: do_rowheight(cursheet); break;
case BLOCK_CLEAR: do_clear(cursheet); update(cursheet); break; case BLOCK_CLEAR: do_clear(cursheet); update(cursheet); break;
case BLOCK_INSERT: do_insert(cursheet); update(cursheet); break; case BLOCK_INSERT: do_insert(cursheet); update(cursheet); break;
case BLOCK_DELETE: do_delete(cursheet); update(cursheet); break; case BLOCK_DELETE: do_delete(cursheet); update(cursheet); break;
@ -1529,13 +1548,13 @@ int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly)
"\n" "\n"
"<p>Original Version: Michael Haardt<br>\n" "<p>Original Version: Michael Haardt<br>\n"
"Current Maintainer: Joerg Walter<br>\n" "Current Maintainer: Joerg Walter<br>\n"
"Contibutions by: Glen Whitney<br>\b" "Contributions by: Glen Whitney<br>\b"
"Home Page: <a href='http://www.syntax-k.de/projekte/teapot/'>http://www.syntax-k.de/projekte/teapot/</a></p>\n" "Home Page: <a href='http://www.syntax-k.de/projekte/teapot/'>http://www.syntax-k.de/projekte/teapot/</a></p>\n"
"This distribution: <a href='https://code.studioinfinity.org/glen/teapot-spreadsheet/'>https://code.studioinfinity.org/glen/teapot-spreadsheet/</a></p>\n" "This distribution: <a href='https://code.studioinfinity.org/glen/teapot-spreadsheet/'>https://code.studioinfinity.org/glen/teapot-spreadsheet/</a></p>\n"
"\n" "\n"
"<p>Copyright 1995-2006 Michael Haardt,<br>\n" "<p>Copyright 1995-2006 Michael Haardt,<br>\n"
"Copyright 2009-2010 Joerg Walter (<a href='mailto:info@syntax-k.de'>info@syntax-k.de</a>)<br>" "Copyright 2009-2010 Joerg Walter (<a href='mailto:info@syntax-k.de'>info@syntax-k.de</a>)<br>"
"Copyright 2019 Glen Whitney</p></center>\n" "Copyright 2019,2023 Glen Whitney</p></center>\n"
"\f" "\f"
"<p>This program is free software: you can redistribute it and/or modify\n" "<p>This program is free software: you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n" "it under the terms of the GNU General Public License as published by\n"
@ -1577,19 +1596,20 @@ int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly)
/* NPAGE -- page down */ /*{{{*/ /* NPAGE -- page down */ /*{{{*/
case K_NPAGE: case K_NPAGE:
{ {
cursheet->offy += (cursheet->maxy-3); cursheet->offy += ((CoordT)(cursheet->maxy)-3);
relmoveto(cursheet, 0, cursheet->maxy-3, 0); relmoveto(cursheet, 0, (CoordT)(cursheet->maxy)-3, 0);
break; break;
} }
/*}}}*/ /*}}}*/
/* PPAGE -- page up */ /*{{{*/ /* PPAGE -- page up */ /*{{{*/
case K_PPAGE: case K_PPAGE:
{ {
cursheet->offy = cursheet->offy >= cursheet->maxy - 3 cursheet->offy =
? cursheet->offy - cursheet->maxy + 3 : 0; cursheet->offy >= (CoordT)(cursheet->maxy) - 3
? cursheet->offy - (CoordT)(cursheet->maxy) + 3 : 0;
relmoveto(cursheet, 0, relmoveto(cursheet, 0,
cursheet->cur[Y] >= (cursheet->maxy - 3) cursheet->cur[Y] >= ((CoordT)(cursheet->maxy) - 3)
? -(cursheet->maxy - 3) : -cursheet->cur[Y], ? -((CoordT)(cursheet->maxy) - 3) : -cursheet->cur[Y],
0); 0);
break; break;
} }
@ -1645,7 +1665,7 @@ int main(int argc, char *argv[])
find_helpfile(helpfile, sizeof(helpfile), argv[0]); find_helpfile(helpfile, sizeof(helpfile), argv[0]);
/* parse options */ /*{{{*/ /* parse options */ /*{{{*/
while ((o=getopt(argc,argv,"bdhnrqHp:?"))!=EOF) switch (o) while ((o=getopt(argc,argv,"bdhnrqHp:F:?"))!=EOF) switch (o)
{ {
/* b -- run batch */ /*{{{*/ /* b -- run batch */ /*{{{*/
case 'b': batch = true; break; case 'b': batch = true; break;
@ -1687,19 +1707,35 @@ int main(int argc, char *argv[])
break; break;
} }
/*}}}*/ /*}}}*/
/* F -- font size */ /*{{{*/
case 'F':
{
long f;
char *end;
f = strtol(optarg, &end, 0);
if (*end || f < 1) {
fprintf(stderr, _("teapot: font size must be positive.\n"));
exit(1);
}
fontsize = (int)f;
break;
}
/*}}}*/
/* default -- includes ? and h */ /*{{{*/ /* default -- includes ? and h */ /*{{{*/
default: default:
{ {
fprintf(stderr,_( fprintf(stderr,_(
"Usage: %s [-a] [-b] [-d]* [-h] [-n|-q] [-H] [-r] [-p digits] [file]\n" "Usage: %s [-abFhHr] [-d]* [-n|-q] [-p digits] [file]\n"
" -a: use ASCII file format as default\n" " -a: use ASCII file format as default\n"
" -b: batch mode\n" " -b: batch mode\n"
" -d: increase debug level, once for each occurrence\n" " -d: increase debug level, once for each occurrence\n"
" -F nn: set font size to nn\n"
" -h: print this message and exit\n" " -h: print this message and exit\n"
" -n|-q: DO NOT or DO display strings in quotes, respectively\n"
" -H: hide row/column headers\n" " -H: hide row/column headers\n"
" -n|-q: DO NOT or DO display strings in quotes, respectively\n"
" -p nn: set decimal precision to nn\n"
" -r: redraw more often\n" " -r: redraw more often\n"
" -p: set decimal precision\n"
), argv[0]); ), argv[0]);
exit(1); exit(1);
} }

View File

@ -17,6 +17,7 @@ extern bool batch;
extern PrecisionLevel def_precision; extern PrecisionLevel def_precision;
extern StringFormat quote; extern StringFormat quote;
extern bool header; extern bool header;
extern int fontsize;
extern int debug_level; extern int debug_level;
extern bool always_redraw; extern bool always_redraw;
extern unsigned int batchln; extern unsigned int batchln;
@ -94,7 +95,8 @@ typedef enum
ADJUST_BACKGROUND = -63, ADJUST_BACKGROUND = -63,
K_EDIT_STYLE_EXPR = -64, K_EDIT_STYLE_EXPR = -64,
ADJUST_DIM = -65, ADJUST_DIM = -65,
ADJUST_ITALIC = -66 ADJUST_ITALIC = -66,
K_ROWHEIGHT = -67
} Key; } Key;
extern int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly); extern int do_sheetcmd(Sheet *cursheet, Key c, bool moveonly);

View File

@ -226,6 +226,7 @@ void initialize_sheet(Sheet *sheet) {
sheet->dim[X] = sheet->dim[Y] = sheet->dim[Z] = 0; sheet->dim[X] = sheet->dim[Y] = sheet->dim[Z] = 0;
sheet->sheet = (Cell**)0; sheet->sheet = (Cell**)0;
sheet->column = (ColWidT*)0; sheet->column = (ColWidT*)0;
sheet->rowhts = (RowHgtT*)0;
sheet->orix = sheet->oriy = 0; sheet->orix = sheet->oriy = 0;
sheet->maxx = sheet->maxy = 0; sheet->maxx = sheet->maxy = 0;
sheet->name = (char*)0; sheet->name = (char*)0;
@ -272,7 +273,7 @@ void resize(Sheet *sheet, CoordT x, CoordT y, CoordT z, bool *qextended)
if (sheet->sheet!=(Cell**)0) free(sheet->sheet); if (sheet->sheet!=(Cell**)0) free(sheet->sheet);
sheet->sheet = dummy.sheet; sheet->sheet = dummy.sheet;
/*}}}*/ /*}}}*/
/* allocate new columns */ /*{{{*/ /* allocate new column widths and row heights */ /*{{{*/
if ((size_t)x > sheet->dim[X] || (size_t)z >= sheet->dim[Z]) if ((size_t)x > sheet->dim[X] || (size_t)z >= sheet->dim[Z])
{ {
dummy.column = malloc(dummy.dim[X] * dummy.dim[Z] * sizeof(ColWidT)); dummy.column = malloc(dummy.dim[X] * dummy.dim[Z] * sizeof(ColWidT));
@ -281,7 +282,7 @@ void resize(Sheet *sheet, CoordT x, CoordT y, CoordT z, bool *qextended)
{ {
if ((size_t)x < sheet->dim[X] && (size_t)z < sheet->dim[Z]) if ((size_t)x < sheet->dim[X] && (size_t)z < sheet->dim[Z])
*(dummy.column + ((size_t)x)*dummy.dim[Z] + (size_t)z) *(dummy.column + ((size_t)x)*dummy.dim[Z] + (size_t)z)
= *(sheet->column + ((size_t)x)*sheet->dim[Z] + z); = *(sheet->column + ((size_t)x)*sheet->dim[Z] + (size_t)z);
else else
*(dummy.column + ((size_t)x)*dummy.dim[Z] + (size_t)z) *(dummy.column + ((size_t)x)*dummy.dim[Z] + (size_t)z)
= DEF_COLUMNWIDTH; = DEF_COLUMNWIDTH;
@ -289,6 +290,21 @@ void resize(Sheet *sheet, CoordT x, CoordT y, CoordT z, bool *qextended)
if (sheet->column != (ColWidT*)0) free(sheet->column); if (sheet->column != (ColWidT*)0) free(sheet->column);
sheet->column = dummy.column; sheet->column = dummy.column;
} }
if ((size_t)(y) > sheet->dim[Y] || (size_t)z > sheet->dim[Z])
{
dummy.rowhts = malloc(dummy.dim[Y] * dummy.dim[Z] * sizeof(RowHgtT));
for (y=0; (size_t)y < dummy.dim[Y]; ++y)
for (z=0; (size_t)z < dummy.dim[Z]; ++z)
{
RowHgtT *dumht = dummy.rowhts + ((size_t)y)*dummy.dim[Z] + (size_t)z;
if ((size_t)y < sheet->dim[Y] && (size_t)z < sheet->dim[Z])
*dumht = *(sheet->rowhts + ((size_t)y)*sheet->dim[Z] + (size_t)z);
else
*dumht = DEF_ROWHEIGHT;
}
if (sheet->rowhts != (RowHgtT*)0) free(sheet->rowhts);
sheet->rowhts = dummy.rowhts;
}
/*}}}*/ /*}}}*/
for (Dimensions dd = X; dd < HYPER; ++dd) sheet->dim[dd] = dummy.dim[dd]; for (Dimensions dd = X; dd < HYPER; ++dd) sheet->dim[dd] = dummy.dim[dd];
} }
@ -408,12 +424,16 @@ void freesheet(Sheet *sheet, int all)
} /*}}}*/ } /*}}}*/
if (sheet->sheet) free(sheet->sheet); if (sheet->sheet) free(sheet->sheet);
if (sheet->column) free(sheet->column); if (sheet->column) free(sheet->column);
if (sheet->rowhts) free(sheet->rowhts);
if (sheet->name) free(sheet->name); if (sheet->name) free(sheet->name);
if (!batch) display_end(sheet); if (!batch) display_end(sheet);
} else { } else {
for (size_t x = 0; x < sheet->dim[X]; ++x) for (size_t x = 0; x < sheet->dim[X]; ++x)
for (size_t z = 0; z < sheet->dim[Z]; ++z) for (size_t z = 0; z < sheet->dim[Z]; ++z)
*(sheet->column + x*sheet->dim[Z] + z) = DEF_COLUMNWIDTH; *(sheet->column + x*sheet->dim[Z] + z) = DEF_COLUMNWIDTH;
for (size_t y = 0; y < sheet->dim[y]; ++y)
for (size_t z = 0; z < sheet->dim[Z]; ++z)
*(sheet->rowhts + y*sheet->dim[Z] + z) = DEF_ROWHEIGHT;
cachelabels(sheet); cachelabels(sheet);
forceupdate(sheet); forceupdate(sheet);
} }
@ -460,6 +480,17 @@ ColWidT columnwidth(Sheet *sheet, CoordT x, CoordT z)
} }
/*}}}*/ /*}}}*/
/* rowheight -- get height of row */ /*{{{*/
ColWidT rowheight(Sheet *sheet, CoordT y, CoordT z)
{
assert(sheet!=(Sheet*)0);
if ((size_t)y < sheet->dim[Y] && (size_t)z < sheet->dim[Z])
return (*(sheet->rowhts + ((size_t)y)*sheet->dim[Z] + (size_t)z));
else return DEF_ROWHEIGHT;
}
/*}}}*/
/* setwidth -- set width of column */ /*{{{*/ /* setwidth -- set width of column */ /*{{{*/
bool setwidth(Sheet *sheet, CoordT x, CoordT z, ColWidT width) bool setwidth(Sheet *sheet, CoordT x, CoordT z, ColWidT width)
{ {
@ -477,6 +508,24 @@ bool setwidth(Sheet *sheet, CoordT x, CoordT z, ColWidT width)
} }
/*}}}*/ /*}}}*/
/* setheight -- set height of row */ /*{{{*/
bool setheight(Sheet *sheet, CoordT y, CoordT z, RowHgtT height)
{
assert(sheet != (Sheet*)0);
bool isbigger = false;
resize(sheet, 1, y, z, &isbigger);
if (isbigger) sheet->changed = true;
RowHgtT *storage = sheet->rowhts + (size_t)y*sheet->dim[Z] + (size_t)z;
if (*storage != height) {
*storage = height;
sheet->changed = true;
return true;
}
return isbigger;
}
/*}}}*/
/* cellwidth -- get width of a cell */ /*{{{*/ /* cellwidth -- get width of a cell */ /*{{{*/
ColWidT cellwidth(Sheet *sheet, const Location at) ColWidT cellwidth(Sheet *sheet, const Location at)
{ {
@ -489,6 +538,18 @@ ColWidT cellwidth(Sheet *sheet, const Location at)
} }
/*}}}*/ /*}}}*/
/* cellheight -- get height of a cell */ /*{{{*/
RowHgtT cellheight(Sheet *sheet, const Location at)
{
/* At the moment this is trivial because there is no vertical
"shadowing". Probably rather than implementing that more
general cell merging would be a preferable way to go
*/
return rowheight(sheet, at[Y], at[Z]);
}
/*}}}*/
/* putcont -- assign new contents */ /*{{{*/ /* putcont -- assign new contents */ /*{{{*/
void puttok(Sheet *sheet, const Location at, Token t, TokVariety v) void puttok(Sheet *sheet, const Location at, Token t, TokVariety v)
{ {
@ -1232,6 +1293,8 @@ const char *saveport(Sheet *sheet, const char *name, unsigned int *count)
{ {
if (y == 0 && columnwidth(sheet,x,z) != DEF_COLUMNWIDTH) if (y == 0 && columnwidth(sheet,x,z) != DEF_COLUMNWIDTH)
fprintf(fp,"W%d %d %zu\n", x, z, columnwidth(sheet,x,z)); fprintf(fp,"W%d %d %zu\n", x, z, columnwidth(sheet,x,z));
if (x == 0 && rowheight(sheet, y, z) != DEF_ROWHEIGHT)
fprintf(fp, "Y%d %d %zu\n", y, z, rowheight(sheet, y, z));
Cell *cell = CELL_ATC(sheet,x,y,z); Cell *cell = CELL_ATC(sheet,x,y,z);
if (cell != NULLCELL) if (cell != NULLCELL)
{ {
@ -1283,6 +1346,7 @@ const char *loadport(Sheet *sheet, const char *name)
size_t width = strlen(buf); size_t width = strlen(buf);
if (width > 0 && buf[width-1] == '\n') buf[--width] = '\0'; if (width > 0 && buf[width-1] == '\n') buf[--width] = '\0';
/*}}}*/ /*}}}*/
bool is_height = false;
switch (buf[0]) switch (buf[0])
{ {
/* C -- parse cell */ /*{{{*/ /* C -- parse cell */ /*{{{*/
@ -1548,16 +1612,21 @@ const char *loadport(Sheet *sheet, const char *name)
break; break;
} }
/*}}}*/ /*}}}*/
/* Y -- row height */
case 'Y':
is_height = true;
/* FALL THROUGH */
/* W -- column width */ /*{{{*/ /* W -- column width */ /*{{{*/
case 'W': case 'W':
{ {
/* parse x and z */ /*{{{*/ /* parse x/y and z */ /*{{{*/
const char *os = buf+1; const char *os = buf+1;
char *ns = buf+1; char *ns = buf+1;
CoordT cx = (CoordT)strtol(os, &ns, 0); CoordT cxy = (CoordT)strtol(os, &ns, 0);
if (os == ns) if (os == ns)
{ {
sprintf(errbuf, _("Parse error for x position in line %d"), line); sprintf(errbuf, _("Parse error for %c position in line %d"),
is_height ? 'y' : 'x', line);
err = errbuf; err = errbuf;
goto eek; goto eek;
} }
@ -1571,10 +1640,10 @@ const char *loadport(Sheet *sheet, const char *name)
goto eek; goto eek;
} }
/*}}}*/ /*}}}*/
/* parse width */ /*{{{*/ /* parse width/height */ /*{{{*/
while (*ns == ' ') ++ns; while (*ns == ' ') ++ns;
os = ns; os = ns;
ColWidT cwidth = (ColWidT)strtol(os, &ns, 0); long extent = strtol(os, &ns, 0);
if (os == ns) if (os == ns)
{ {
sprintf(errbuf, _("Parse error for width in line %d"), line); sprintf(errbuf, _("Parse error for width in line %d"), line);
@ -1582,7 +1651,8 @@ const char *loadport(Sheet *sheet, const char *name)
goto eek; goto eek;
} }
/*}}}*/ /*}}}*/
setwidth(sheet, cx, cz, cwidth); if (is_height) setheight(sheet, cxy, cz, (RowHgtT)extent);
else setwidth(sheet, cxy, cz, (ColWidT)extent);
break; break;
} }
/*}}}*/ /*}}}*/

View File

@ -13,6 +13,7 @@ extern "C" {
#define ASCENDING 001 #define ASCENDING 001
typedef size_t ColWidT; typedef size_t ColWidT;
typedef size_t RowHgtT; /* Note measured in units of ROWHEIGHT_DENOMINATOR */
typedef struct typedef struct
{ {
@ -38,9 +39,10 @@ typedef struct
CoordT offx, offy; CoordT offx, offy;
Cell **sheet; Cell **sheet;
ColWidT *column; ColWidT *column;
RowHgtT *rowhts;
size_t dim[HYPER]; size_t dim[HYPER];
size_t orix, oriy; size_t orix, oriy;
CoordT maxx, maxy; size_t maxx, maxy;
size_t width; size_t width;
char *name; char *name;
void *display; void *display;
@ -86,6 +88,9 @@ void freecellofsheet(Sheet *sheet, const Location at);
ColWidT columnwidth(Sheet *sheet, CoordT x, CoordT z); ColWidT columnwidth(Sheet *sheet, CoordT x, CoordT z);
bool setwidth(Sheet *sheet, CoordT x, CoordT z, ColWidT width); bool setwidth(Sheet *sheet, CoordT x, CoordT z, ColWidT width);
ColWidT cellwidth(Sheet *sheet, const Location at); ColWidT cellwidth(Sheet *sheet, const Location at);
RowHgtT rowheight(Sheet *sheet, CoordT y, CoordT z);
bool setheight(Sheet *sheet, CoordT y, CoordT x, RowHgtT height);
RowHgtT cellheight(Sheet *sheet, const Location at);
void puttok(Sheet *sheet, const Location at, Token t, TokVariety v); void puttok(Sheet *sheet, const Location at, Token t, TokVariety v);
Token recompvalue(Sheet *sheet, const Location at); Token recompvalue(Sheet *sheet, const Location at);
Token evaluate_at(Token t, Sheet *sheet, const Location at); Token evaluate_at(Token t, Sheet *sheet, const Location at);

View File

@ -272,15 +272,16 @@ static int do_block(Sheet *cursheet)
} }
int show_menu(Sheet *cursheet) Key show_menu(Sheet *cursheet)
{ {
int c = K_INVALID; int c = K_INVALID;
do do
{ {
const char* menu[] = const char* menu[] =
{ _("aA)ttributes"), _("wW)idth"), _("bB)lock"), _("fF)ile"), { _("aA)ttributes"), _("wW)idth"), _("hH)eight"), _("bB)lock"),
_("gG)oto"), _("sS)hell"), _("vV)ersion"), _("qQ)uit"), NULL _("fF)ile"), _("gG)oto"), _("sS)hell"), _("vV)ersion"),
_("qQ)uit"), NULL
}; };
switch (c=line_menu(_("Main menu:"),menu,0)) switch (c=line_menu(_("Main menu:"),menu,0))
{ {
@ -288,12 +289,13 @@ int show_menu(Sheet *cursheet)
case -1: c = KEY_CANCEL; break; case -1: c = KEY_CANCEL; break;
case 0: c = do_attribute(cursheet); break; case 0: c = do_attribute(cursheet); break;
case 1: c = K_COLWIDTH; break; case 1: c = K_COLWIDTH; break;
case 2: c = do_block(cursheet); break; case 2: c = K_ROWHEIGHT; break;
case 3: c = do_file(cursheet); break; case 3: c = do_block(cursheet); break;
case 4: c = K_GOTO; break; case 4: c = do_file(cursheet); break;
case 5: do_shell(); c = KEY_CANCEL; break; case 5: c = K_GOTO; break;
case 6: c = K_ABOUT; break; case 6: do_shell(); c = KEY_CANCEL; break;
case 7: c = K_QUIT; break; case 7: c = K_ABOUT; break;
case 8: c = K_QUIT; break;
default: assert(0); default: assert(0);
} }
} while (c == K_INVALID); } while (c == K_INVALID);
@ -327,8 +329,8 @@ static void do_bg(void)
void display_main(Sheet *cursheet) void display_main(Sheet *cursheet)
{ {
cursheet->maxx = COLS; cursheet->maxx = (size_t)COLS;
cursheet->maxy = LINES-1; cursheet->maxy = (size_t)(LINES-1);
Key k; Key k;
do do
@ -396,10 +398,15 @@ void redraw_cell(Sheet *sheet, const Location at )
update(sheet); update(sheet);
} }
static RowHgtT eff_height(Sheet *sheet, CoordT y) {
RowHgtT eff = rowheight(sheet, y, sheet->cur[Z]) / ROWHEIGHT_DENOMINATOR;
if (eff == 0) return 1;
return eff;
}
/* redraw_sheet -- draw a sheet with cell cursor */ /* redraw_sheet -- draw a sheet with cell cursor */
void redraw_sheet(Sheet *sheet) void redraw_sheet(Sheet *sheet)
{ {
int x,y;
char pbuf[80]; char pbuf[80];
char *buf=malloc(128); char *buf=malloc(128);
size_t bufsz=128; size_t bufsz=128;
@ -421,18 +428,31 @@ void redraw_sheet(Sheet *sheet)
--(sheet->cur[X]); --(sheet->cur[X]);
assert(sheet->cur[X] >= 0); assert(sheet->cur[X] >= 0);
} }
if (sheet->cur[Y] - sheet->offy > sheet->maxy - 2 - (header ? 1 : 0)) /* Calculate the nearest Y offset that will show the current row */
sheet->offy = sheet->cur[Y] - sheet->maxy + 2 + (header ? 1 : 0);
if (sheet->cur[Y] < sheet->offy) sheet->offy = sheet->cur[Y]; if (sheet->cur[Y] < sheet->offy) sheet->offy = sheet->cur[Y];
else {
size_t available = sheet->maxy - 2 - (header ? 1 : 0);
CoordT newoffy = sheet->cur[Y];
size_t needed = eff_height(sheet, newoffy);
while (needed < available && newoffy > 0) {
RowHgtT prevhgt = eff_height(sheet, newoffy - 1);
if (needed + prevhgt > available) break;
needed += prevhgt;
--newoffy;
}
if (newoffy > sheet->offy) sheet->offy = newoffy;
}
/* Calculate the nearest X offset that will show the current column */
if (sheet->cur[X] < sheet->offx) sheet->offx = sheet->cur[X]; if (sheet->cur[X] < sheet->offx) sheet->offx = sheet->cur[X];
size_t width = header ? 4 : 0; else {
bool again; size_t width = header ? 4 : 0;
size_t col; bool again;
do size_t col;
{ do
{
again = false; again = false;
col = 0; col = 0;
for (x = sheet->offx; for (CoordT x = sheet->offx;
width <= (size_t)(sheet->maxx); width <= (size_t)(sheet->maxx);
width += columnwidth(sheet, x, sheet->cur[Z]), ++x, ++col); width += columnwidth(sheet, x, sheet->cur[Z]), ++x, ++col);
--col; --col;
@ -444,7 +464,8 @@ void redraw_sheet(Sheet *sheet)
sheet->offx++; again = true; sheet->offx++; again = true;
} }
} }
} while (again); } while (again);
}
short curcp = 1; short curcp = 1;
init_pair(curcp, DefaultCN[FOREGROUND], COLOR_YELLOW); init_pair(curcp, DefaultCN[FOREGROUND], COLOR_YELLOW);
@ -452,15 +473,15 @@ void redraw_sheet(Sheet *sheet)
if (header) { if (header) {
(void)wattron(stdscr,DEF_NUMBER); (void)wattron(stdscr,DEF_NUMBER);
/* draw x numbers */ /* draw x numbers */
for (width=4; width < (size_t)(sheet->maxx); ++width) for (size_t width=4; width < (size_t)(sheet->maxx); ++width)
mvwaddch(stdscr, (int)(sheet->oriy), (int)(sheet->orix + width), mvwaddch(stdscr, (int)(sheet->oriy), (int)(sheet->orix + width),
(chtype)(unsigned char)' '); (chtype)(unsigned char)' ');
for (width = 4, x = sheet->offx; width < (size_t)(sheet->maxx); ColWidT width = 4;
width += col, ++x) for (CoordT x = sheet->offx; width < sheet->maxx; ++x)
{ {
short usecp = 0; short usecp = 0;
if (x == sheet->cur[X]) usecp = curcp; if (x == sheet->cur[X]) usecp = curcp;
col = columnwidth(sheet, x, sheet->cur[Z]); ColWidT col = columnwidth(sheet, x, sheet->cur[Z]);
if (bufsz<(size_t)(col*UTF8SZ+1)) buf=realloc(buf,bufsz=(size_t)(col*UTF8SZ+1)); if (bufsz<(size_t)(col*UTF8SZ+1)) buf=realloc(buf,bufsz=(size_t)(col*UTF8SZ+1));
snprintf(buf,bufsz,"%d",x); snprintf(buf,bufsz,"%d",x);
if (mbslen(buf)>col) { if (mbslen(buf)>col) {
@ -473,18 +494,27 @@ void redraw_sheet(Sheet *sheet)
buf[(size_t)(sheet->maxx)-width] = '\0'; buf[(size_t)(sheet->maxx)-width] = '\0';
wcolor_set(stdscr, usecp, NULL); wcolor_set(stdscr, usecp, NULL);
mvwaddstr(stdscr, (int)(sheet->oriy), (int)(sheet->orix+width), buf); mvwaddstr(stdscr, (int)(sheet->oriy), (int)(sheet->orix+width), buf);
ColWidT used = strlen(buf);
while (used++ < col) waddch(stdscr, (chtype)(unsigned char)' ');
wcolor_set(stdscr, 0, NULL); wcolor_set(stdscr, 0, NULL);
width += col;
} }
/* draw y numbers */ /* draw y numbers */
for (y=1; y < sheet->maxy - 1; ++y) { RowHgtT height = 1;
for (CoordT y = sheet->offy; height + 1 < sheet->maxy; ++y) {
short usecp = 0; short usecp = 0;
CoordT realy = y - 1 + sheet->offy; if (y == sheet->cur[Y]) usecp = curcp;
if (realy == sheet->cur[Y]) usecp = curcp;
wcolor_set(stdscr, usecp, NULL); wcolor_set(stdscr, usecp, NULL);
(void)mvwprintw(stdscr, y + (CoordT)(sheet->oriy), (CoordT)(sheet->orix), (void)mvwprintw(stdscr, (int)(height+sheet->oriy), (int)sheet->orix,
"%-4d", y-1 + (int)(sheet->offy)); "%-4d", y);
RowHgtT rows = eff_height(sheet, y);
for (RowHgtT extra = 1; extra < rows; ++extra) {
mvwaddstr(stdscr, (int)(height+extra+sheet->oriy), (int)sheet->orix,
" ");
}
wcolor_set(stdscr, 0, NULL); wcolor_set(stdscr, 0, NULL);
height += eff_height(sheet, y);
} }
(void)wattroff(stdscr,DEF_NUMBER); (void)wattroff(stdscr,DEF_NUMBER);
@ -494,11 +524,14 @@ void redraw_sheet(Sheet *sheet)
} }
++curcp; ++curcp;
/* draw elements */ /* draw elements */
for (y = header ? 1 : 0; y < sheet->maxy - 1; ++y) RowHgtT height = header ? 1 : 0;
for (width = header ? 4 : 0, x = sheet->offx; for (CoordT y = sheet->offy; height + 1 < sheet->maxy; ++y) {
width < (size_t)sheet->maxx; RowHgtT rows = eff_height(sheet, y);
ColWidT width = header ? 4 : 0;
for (CoordT x = sheet->offx;
width < sheet->maxx;
width += columnwidth(sheet, x, sheet->cur[Z]), ++x) width += columnwidth(sheet, x, sheet->cur[Z]), ++x)
{ {
size_t size,realsize,fill, cutoff = 0; size_t size,realsize,fill, cutoff = 0;
int realx = x; int realx = x;
if (x == sheet->offx) { if (x == sheet->offx) {
@ -511,7 +544,7 @@ void redraw_sheet(Sheet *sheet)
cutoff += columnwidth(sheet, realx, sheet->cur[Z]); cutoff += columnwidth(sheet, realx, sheet->cur[Z]);
} }
} }
tmp[X] = realx; tmp[Y] = y - (header ? 1 : 0) + sheet->offy; tmp[X] = realx; tmp[Y] = y;
tmp[Z] = sheet->cur[Z]; tmp[Z] = sheet->cur[Z];
cell = safe_cell_at(sheet, tmp); cell = safe_cell_at(sheet, tmp);
Style sc = getstyle(sheet, tmp); Style sc = getstyle(sheet, tmp);
@ -548,21 +581,30 @@ void redraw_sheet(Sheet *sheet)
wcolor_set(stdscr, usecp, NULL); wcolor_set(stdscr, usecp, NULL);
bool invert = bool invert =
(ms != UNMARKED) && loc_in_box(tmp, sheet->mark1, sheet->mark2); (ms != UNMARKED) && loc_in_box(tmp, sheet->mark1, sheet->mark2);
if (x == sheet->cur[X] if (x == sheet->cur[X] && y == sheet->cur[Y])
&& (y - (header ? 1 : 0) + sheet->offy == sheet->cur[Y]))
invert = (ms == MARKING) ? true : !invert; invert = (ms == MARKING) ? true : !invert;
if (invert) (void)wattron(stdscr,DEF_CELLCURSOR); if (invert) (void)wattron(stdscr,DEF_CELLCURSOR);
if (sc.dim) wattron(stdscr, A_DIM); if (sc.dim) wattron(stdscr, A_DIM);
if (sc.bold) wattron(stdscr, A_BOLD); if (sc.bold) wattron(stdscr, A_BOLD);
if (sc.underline) wattron(stdscr, A_UNDERLINE); if (sc.underline) wattron(stdscr, A_UNDERLINE);
(void)mvwaddstr(stdscr, y+(int)(sheet->oriy), (void)mvwaddstr(stdscr, (int)(height + sheet->oriy),
(int)(sheet->orix + width), (int)(width + sheet->orix),
buf+cutoff); buf+cutoff);
for (fill=mbslen(buf+cutoff); fill<realsize; ++fill) for (fill=mbslen(buf+cutoff); fill<realsize; ++fill)
(void)waddch(stdscr,(chtype)(unsigned char)' '); (void)waddch(stdscr,(chtype)(unsigned char)' ');
for (RowHgtT extra = 1; extra < rows; ++extra) {
mvwaddstr(stdscr,
(int)(height + extra + sheet->oriy),
(int)(width + sheet->orix),
" ");
for (fill = 1; fill < realsize; ++fill)
(void)waddch(stdscr, (chtype)(unsigned char)' ');
}
wcolor_set(stdscr, 0, NULL); wcolor_set(stdscr, 0, NULL);
wstandend(stdscr); wstandend(stdscr);
} }
}
height += rows;
} }
/* draw contents of current element */ /* draw contents of current element */
@ -596,11 +638,11 @@ void redraw_sheet(Sheet *sheet)
FLT_COMPACT, -1, TRUNCATED_ERROR, &ic); FLT_COMPACT, -1, TRUNCATED_ERROR, &ic);
} }
} }
*mbspos(buf, sheet->maxx) = 0; *mbspos(buf, (int)sheet->maxx) = 0;
(void)mvwaddstr(stdscr, (int)(sheet->oriy) + sheet->maxy - 1, (void)mvwaddstr(stdscr, (int)(sheet->oriy + sheet->maxy) - 1,
(int)(sheet->orix), buf); (int)(sheet->orix), buf);
for (col = mbslen(buf); col < (size_t)sheet->maxx; ++col) for (size_t col = mbslen(buf); col < sheet->maxx; ++col)
(void)waddch(stdscr, ' '); (void)waddch(stdscr, ' ');
} }
@ -1081,7 +1123,9 @@ static Key wgetc(void)
/* Control R, recalculate sheet */ /* Control R, recalculate sheet */
case '\022': return K_RECALC; case '\022': return K_RECALC;
/* Control S, clock sheet */ /* F8, F9 or Control S, clock sheet */
case KEY_F(8):
case KEY_F(9):
case '\023': return K_CLOCK; case '\023': return K_CLOCK;
/* Control X, get one more key */ /* Control X, get one more key */

View File

@ -1,4 +1,12 @@
# data file for the Fltk User Interface Designer (fluid) # data file for the Fltk User Interface Designer (fluid)
# Code replacements for dummy numerical constants:
# 9999100/*fontsize*/
# 9999112/*fontsize + 12*/
# 9999114/*fontsize + 14*/
# 9999110/*fontsize + 10*/
# 9999224/*2*fontsize + 24*/
# 99990336/*600 - 3*fontsize - 36*/
# 99990112/*600 - fontsize - 12*/
version 1.0300 version 1.0300
header_name {.h} header_name {.h}
code_name {.cxx} code_name {.cxx}
@ -41,6 +49,7 @@ class TeapotTable {open : {public Fl_Table}}
{ {
decl {Sheet *cursheet;} {protected local} decl {Sheet *cursheet;} {protected local}
decl {bool cut, updating;} {protected local} decl {bool cut, updating;} {protected local}
decl {int unit_width, unit_height;} {protected local}
decl {static const TableContext ACTION = (TableContext)(1<<8);} decl {static const TableContext ACTION = (TableContext)(1<<8);}
{public local} {public local}
decl {static const TableContext REFRESH = (TableContext)(1<<9);} decl {static const TableContext REFRESH = (TableContext)(1<<9);}
@ -48,14 +57,25 @@ class TeapotTable {open : {public Fl_Table}}
Function Function
{TeapotTable(int x, int y, int w, int h, const char *l=0) : {TeapotTable(int x, int y, int w, int h, const char *l=0) :
Fl_Table(x, y, w, h, l), cut(false), updating(false)} {open} {code Fl_Table(x, y, w, h, l), cut(false), updating(false),
unit_width(10), unit_height(0)} {open} {code
{ {
end(); end();
col_resize_min(10); col_resize_min(unit_width);
col_resize(true); col_resize(true);
col_header(header); col_header(header);
row_resize(false); unit_height = fl_height(FL_HELVETICA, fontsize);
col_header_height(unit_height);
fl_font(FL_HELVETICA, fontsize);
int ww = 0, hh = 0;
fl_measure("8888", ww, hh, 0);
int min_row_height = (unit_height + ROWHEIGHT_DENOMINATOR/2 - 1)
/ ROWHEIGHT_DENOMINATOR;
if (min_row_height < 1) min_row_height = 1;
row_resize_min(min_row_height);
row_resize(true);
row_header(header); row_header(header);
row_header_width(ww + unit_width);
set_visible_focus(); set_visible_focus();
table_box(FL_THIN_UP_FRAME); table_box(FL_THIN_UP_FRAME);
} {} } } {} }
@ -92,7 +112,7 @@ class TeapotTable {open : {public Fl_Table}}
case CONTEXT_ENDPAGE: case CONTEXT_ENDPAGE:
W = xx-x()-2; H = yy-y()-2; W = xx-x()-2; H = yy-y()-2;
xx = x()+2; yy = y()+2; xx = x()+2; yy = y()+2;
fl_font(FL_HELVETICA | FL_BOLD, 14); fl_font(FL_HELVETICA | FL_BOLD, fontsize);
fl_push_clip(xx, yy, W, H); fl_push_clip(xx, yy, W, H);
fl_draw_box(FL_DIAMOND_UP_BOX, xx, yy, W, H, col_header_color()); fl_draw_box(FL_DIAMOND_UP_BOX, xx, yy, W, H, col_header_color());
fl_color(FL_INACTIVE_COLOR); fl_color(FL_INACTIVE_COLOR);
@ -107,7 +127,7 @@ class TeapotTable {open : {public Fl_Table}}
break; break;
case CONTEXT_COL_HEADER: { case CONTEXT_COL_HEADER: {
fl_font(FL_HELVETICA | FL_BOLD, 14); fl_font(FL_HELVETICA | FL_BOLD, fontsize);
fl_push_clip(xx, yy, W, H); fl_push_clip(xx, yy, W, H);
Fl_Color hd_clr = col_header_color(); Fl_Color hd_clr = col_header_color();
if (C == cursheet->cur[X]) hd_clr = tpt_selection_version(hd_clr); if (C == cursheet->cur[X]) hd_clr = tpt_selection_version(hd_clr);
@ -120,7 +140,7 @@ class TeapotTable {open : {public Fl_Table}}
} }
case CONTEXT_ROW_HEADER: { case CONTEXT_ROW_HEADER: {
fl_font(FL_HELVETICA | FL_BOLD, 14); fl_font(FL_HELVETICA | FL_BOLD, fontsize);
fl_push_clip(xx, yy, W, H); fl_push_clip(xx, yy, W, H);
Fl_Color hd_clr = row_header_color(); Fl_Color hd_clr = row_header_color();
if (R == cursheet->cur[Y]) hd_clr = tpt_selection_version(hd_clr); if (R == cursheet->cur[Y]) hd_clr = tpt_selection_version(hd_clr);
@ -171,7 +191,7 @@ class TeapotTable {open : {public Fl_Table}}
Fl_Font cellfont = FL_HELVETICA; Fl_Font cellfont = FL_HELVETICA;
if (sc.bold) cellfont |= FL_BOLD; if (sc.bold) cellfont |= FL_BOLD;
if (sc.italic) cellfont |= FL_ITALIC; if (sc.italic) cellfont |= FL_ITALIC;
fl_font(cellfont, 14); fl_font(cellfont, fontsize);
size_t ulen = printvalue(s, sizeof(s), 0, quote, sc.fform, size_t ulen = printvalue(s, sizeof(s), 0, quote, sc.fform,
sc.precision, cursheet, test); sc.precision, cursheet, test);
@ -216,21 +236,29 @@ class TeapotTable {open : {public Fl_Table}}
{ {
if (updating) return; if (updating) return;
updating = true; updating = true;
if (debug_level > 2) if (debug_level > 1)
printf("update_table: %zux%zu@%i,%i; %i[%i], %i[%i]\\n", printf("update_table: %zux%zu@%i,%i; %i[%lu], %i[%lu]\\n",
cursheet->dim[X], cursheet->dim[Y], cursheet->dim[X], cursheet->dim[Y],
cursheet->cur[X], cursheet->cur[Y], cursheet->cur[X], cursheet->cur[Y],
cursheet->offx, cursheet->maxx, cursheet->offx, cursheet->maxx,
cursheet->offy, cursheet->maxy); cursheet->offy, cursheet->maxy);
bool no_table = (cols() == 0) || (rows() == 0);
if (cursheet->dim[X] > (size_t)cols()) cols(cursheet->dim[X]); if (cursheet->dim[X] > (size_t)cols()) cols(cursheet->dim[X]);
if (no_table) col_width_all(DEF_COLUMNWIDTH*unit_width);
if (cursheet->dim[Y] > (size_t)rows()) rows(cursheet->dim[Y]); if (cursheet->dim[Y] > (size_t)rows()) rows(cursheet->dim[Y]);
if (no_table) row_height_all(unit_height);
adjust_outside(); adjust_outside();
for (int x = 0; (size_t)x < cursheet->dim[X]; x++) { for (int x = 0; (size_t)x < cursheet->dim[X]; x++) {
int w = columnwidth(cursheet, x, cursheet->cur[Z])*10; int w = columnwidth(cursheet, x, cursheet->cur[Z])*unit_width;
if (col_width(x) != w) col_width(x, w); if (col_width(x) != w) col_width(x, w);
} }
for (int y = 0; (size_t)y < cursheet->dim[Y]; ++y) {
int h = rowheight(cursheet, y, cursheet->cur[Z])*unit_height
/ ROWHEIGHT_DENOMINATOR;
if (row_height(y) != h) row_height(y, h);
}
col_position(cursheet->offx); col_position(cursheet->offx);
row_position(cursheet->offy); row_position(cursheet->offy);
set_selection(cursheet->cur[Y], cursheet->cur[X], set_selection(cursheet->cur[Y], cursheet->cur[X],
@ -257,25 +285,34 @@ class TeapotTable {open : {public Fl_Table}}
cursheet->marking = MARKED; cursheet->marking = MARKED;
} }
moveto(cursheet, current_col, current_row, -1); moveto(cursheet, current_col, current_row, -1);
visible_cells(cursheet->offy, cursheet->maxy, int lastx, lasty;
cursheet->offx, cursheet->maxx); visible_cells(cursheet->offy, lasty,
cursheet->maxx -= cursheet->offx; cursheet->offx, lastx);
cursheet->maxy -= cursheet->offy; cursheet->maxx = (size_t)(lastx - cursheet->offx);
cursheet->maxy = (size_t)(lasty - cursheet->offy);
if (is_interactive_resize()) { if (is_interactive_resize()) {
for (size_t C = 0; C < cursheet->dim[X]; ++C) { for (size_t C = 0; C < cursheet->dim[X]; ++C) {
size_t w = (col_width(C) + 5)/10; size_t w = (col_width(C) + unit_width/2)/unit_width;
if (w != columnwidth(cursheet, C, cursheet->cur[Z])) if (w != columnwidth(cursheet, C, cursheet->cur[Z]))
setwidth(cursheet, C, cursheet->cur[Z], w); setwidth(cursheet, C, cursheet->cur[Z], w);
} }
for (size_t R = 0; R < cursheet->dim[Y]; ++R) {
size_t h =
(row_height(R)*ROWHEIGHT_DENOMINATOR + unit_height/2)
/ unit_height;
if (h != rowheight(cursheet, R, cursheet->cur[Z]))
setheight(cursheet, R, cursheet->cur[Z], h);
}
} }
updating = false; updating = false;
if (debug_level > 2) if (debug_level > 1)
printf("upd_sheet: %ix%i@%i,%i; %i[%i], %i[%i] (%i,%i)-(%i,%i)\\n", printf(
cols(), rows(), cursheet->cur[X], cursheet->cur[Y], "upd_sheet: %ix%i@%i,%i; %i[%lu], %i[%lu] (%i,%i)-(%i,%i)\\n",
cursheet->offx, cursheet->maxx, cols(), rows(), cursheet->cur[X], cursheet->cur[Y],
cursheet->offy, cursheet->maxy, x1, y1, x2, y2); cursheet->offx, cursheet->maxx,
cursheet->offy, cursheet->maxy, x1, y1, x2, y2);
} {} } } {} }
Function Function
@ -291,6 +328,8 @@ class TeapotTable {open : {public Fl_Table}}
case FL_Escape: k = K_INVALID; break; case FL_Escape: k = K_INVALID; break;
case FL_BackSpace: k = K_BACKSPACE; break; case FL_BackSpace: k = K_BACKSPACE; break;
case FL_F+1: k = ctrl?K_ABOUT:K_HELP; break; case FL_F+1: k = ctrl?K_ABOUT:K_HELP; break;
case FL_F+2: k = K_LOADMENU; break;
case FL_F+3: k = K_SAVE; break;
case FL_F+8: k = ctrl?K_RECALC:K_CLOCK; break; case FL_F+8: k = ctrl?K_RECALC:K_CLOCK; break;
case FL_F+9: k = ctrl?K_RECALC:K_CLOCK; break; case FL_F+9: k = ctrl?K_RECALC:K_CLOCK; break;
case FL_F+10: k = (Key)'/'; break; case FL_F+10: k = (Key)'/'; break;
@ -360,14 +399,14 @@ class TeapotTable {open : {public Fl_Table}}
case FL_Page_Up: case FL_Page_Up:
k = shift ? K_PSHEET : ctrl ? K_FIRSTL : K_PPAGE; k = shift ? K_PSHEET : ctrl ? K_FIRSTL : K_PPAGE;
break; break;
default:
/* Handle shifted keys */
if (Fl::event_length() == 1) k = (Key)(Fl::event_text()[0]);
} }
/* This short circuit perhaps needs an explanation: */
if (k > 0 && (ctrl || alt)) return 0; if (k > 0 && (ctrl || alt)) return 0;
// Quick and dirty upper-case fix, fails for international chars on keyboards...
if (shift && !alt && !ctrl && k >= 'a' && k <= 'z')
k = (Key)(k - 'a' + 'A');
do_sheetcmd(cursheet, k, cursheet->moveonly); do_sheetcmd(cursheet, k, cursheet->moveonly);
do_callback(ACTION, 0, 0); do_callback(ACTION, 0, 0);
redraw(); redraw();
@ -399,7 +438,7 @@ class TeapotTable {open : {public Fl_Table}}
if (!cols() || !rows()) { cols(1); rows(1); } if (!cols() || !rows()) { cols(1); rows(1); }
visible_cells(y1, y2, x1, x2); visible_cells(y1, y2, x1, x2);
if (debug_level > 2) if (debug_level > 1)
printf("adj: (%i,%i)-(%i,%i) %ix%i\\n", x1, y1, x2, y2, printf("adj: (%i,%i)-(%i,%i) %ix%i\\n", x1, y1, x2, y2,
cols(), rows()); cols(), rows());
if (x2+2 < cols() && (size_t)cols() > cursheet->dim[X]) if (x2+2 < cols() && (size_t)cols() > cursheet->dim[X])
@ -411,6 +450,8 @@ class TeapotTable {open : {public Fl_Table}}
//printf(" : t: %i, w: %i, p: %i, r: %i\\n", tow, w, xpos, x2+1); //printf(" : t: %i, w: %i, p: %i, r: %i\\n", tow, w, xpos, x2+1);
cols(x2+1); cols(x2+1);
} }
visible_cells(y1, y2, x1, x2);
cursheet->width = x2 - x1 + 1;
if (y2+2 < rows() && (size_t)rows() > cursheet->dim[Y]) if (y2+2 < rows() && (size_t)rows() > cursheet->dim[Y])
rows((size_t)y2+2 < cursheet->dim[Y] ? cursheet->dim[Y] : y2+2); rows((size_t)y2+2 < cursheet->dim[Y] ? cursheet->dim[Y] : y2+2);
@ -463,218 +504,229 @@ class MainWindow {open}
table->update_table(); table->update_table();
table->redraw(); table->redraw();
} }
open xywh {0 0 800 25} class Fl_Sys_Menu_Bar open xywh {0 0 800 9999112} class Fl_Sys_Menu_Bar
code0 {
menu->textsize(fontsize);
}
} }
{ {
Submenu {} {label {&File} xywh {25 25 67 24} } { Submenu {} {label {&File} xywh {25 25 67 24} labelsize 0 } {
MenuItem {} { MenuItem {} {
label {&Open...} label {&Open...}
user_data K_LOADMENU user_data K_LOADMENU
xywh {5 5 30 20} shortcut 0x4006f xywh {5 5 30 20} labelsize 0 shortcut 0x4006f
} }
MenuItem {} { MenuItem {} {
label {&Save} label {&Save}
user_data K_SAVE user_data K_SAVE
xywh {0 0 30 20} shortcut 0x40073 xywh {0 0 30 20} labelsize 0 shortcut 0x40073
} }
MenuItem {} { MenuItem {} {
label {Save &As...} label {Save &As...}
user_data K_NAME user_data K_NAME
xywh {0 0 30 20} shortcut 0x50053 divider xywh {0 0 30 20} labelsize 0 shortcut 0x50053 divider
} }
MenuItem {} { MenuItem {} {
label {&Quit} label {&Quit}
user_data K_QUIT user_data K_QUIT
xywh {0 0 30 20} shortcut 0x40071 xywh {0 0 30 20} labelsize 0 shortcut 0x40071
} }
} }
Submenu {} {label {&Block} xywh {25 25 67 24} } { Submenu {} {label {&Block} xywh {25 25 67 24} labelsize 0 } {
MenuItem {} { MenuItem {} {
label {&Insert} label {&Insert}
user_data BLOCK_INSERT user_data BLOCK_INSERT
xywh {0 0 30 20} shortcut 0x90069 xywh {0 0 30 20} labelsize 0 shortcut 0x90069
} }
MenuItem {} { MenuItem {} {
label {&Delete} label {&Delete}
user_data BLOCK_DELETE user_data BLOCK_DELETE
xywh {0 0 30 20} shortcut 0x90064 divider xywh {0 0 30 20} labelsize 0 shortcut 0x90064 divider
} }
MenuItem {} { MenuItem {} {
label {&Move} label {&Move}
user_data BLOCK_MOVE user_data BLOCK_MOVE
xywh {0 0 30 20} shortcut 0x9006d xywh {0 0 30 20} labelsize 0 shortcut 0x9006d
} }
MenuItem {} { MenuItem {} {
label {&Copy} label {&Copy}
user_data BLOCK_COPY user_data BLOCK_COPY
xywh {0 0 36 21} shortcut 0x90063 divider xywh {0 0 36 21} labelsize 0 shortcut 0x90063 divider
} }
MenuItem {} { MenuItem {} {
label {&Fill} label {&Fill}
user_data BLOCK_FILL user_data BLOCK_FILL
xywh {0 0 36 21} shortcut 0x90066 xywh {0 0 36 21} labelsize 0 shortcut 0x90066
} }
MenuItem {} { MenuItem {} {
label {FillWith} label {FillWith}
user_data FILL_BLOCK user_data FILL_BLOCK
xywh {0 0 36 30} xywh {0 0 36 30} labelsize 0 }
}
MenuItem {} { MenuItem {} {
label {C&lear} label {C&lear}
user_data BLOCK_CLEAR user_data BLOCK_CLEAR
xywh {0 0 36 21} shortcut 0x9006c divider xywh {0 0 36 21} labelsize 0 shortcut 0x9006c divider
} }
MenuItem {} { MenuItem {} {
label {&Sort} label {&Sort}
user_data BLOCK_SORT user_data BLOCK_SORT
xywh {0 0 36 21} shortcut 0x90073 xywh {0 0 36 21} labelsize 0 shortcut 0x90073
} }
MenuItem {} { MenuItem {} {
label {Mi&rror} label {Mi&rror}
user_data BLOCK_MIRROR user_data BLOCK_MIRROR
xywh {0 0 36 21} shortcut 0x90072 xywh {0 0 36 21} labelsize 0 shortcut 0x90072
} }
} }
Submenu {} {label {&View} xywh {0 0 70 21}} { Submenu {} {label {&View} xywh {0 0 70 21} labelsize 0 } {
MenuItem {} { MenuItem {} {
label {Column &Width...} label {Column &Width...}
user_data K_COLWIDTH user_data K_COLWIDTH
xywh {0 0 36 21} shortcut 0x80077 xywh {0 0 36 21} labelsize 0 shortcut 0x80077
}
MenuItem {} {
label {Row &Height...}
user_data K_ROWHEIGHT
xywh {0 0 36 21} labelsize 0 shortcut 0x80068
} }
MenuItem {} { MenuItem {} {
label {&Goto} label {&Goto}
user_data K_GOTO user_data K_GOTO
xywh {0 0 36 21} shortcut 0x40067 xywh {0 0 36 21} labelsize 0 shortcut 0x40067
} }
} }
Submenu {} {label {F&ormat} open xywh {5 5 70 21}} { Submenu {} {label {F&ormat} open xywh {5 5 70 21} labelsize 0 } {
MenuItem {} { MenuItem {} {
label {L&abel...} label {L&abel...}
user_data ADJUST_LABEL user_data ADJUST_LABEL
xywh {0 0 36 21} shortcut 0x80061 divider xywh {0 0 36 21} labelsize 0 shortcut 0x80061 divider
} }
MenuItem dim { MenuItem dim {
label {&Dim} label {&Dim}
user_data ADJUST_DIM user_data ADJUST_DIM
protected xywh {0 0 34 21} protected xywh {0 0 34 21} labelsize 0 shortcut 0x40064
code0 {o->flags |= FL_MENU_TOGGLE;} code0 {o->flags |= FL_MENU_TOGGLE;}
} }
MenuItem bold { MenuItem bold {
label {&Bold} label {&Bold}
user_data ADJUST_BOLD user_data ADJUST_BOLD
protected xywh {0 0 34 21} shortcut 0x80062 protected xywh {0 0 34 21} labelsize 0 shortcut 0x40062
code0 {o->flags |= FL_MENU_TOGGLE;} code0 {o->flags |= FL_MENU_TOGGLE;}
} }
MenuItem italic { MenuItem italic {
label {&Italic} label {&Italic}
user_data ADJUST_ITALIC user_data ADJUST_ITALIC
protected xywh {0 0 34 21} protected xywh {0 0 34 21} labelsize 0 shortcut 0x40069
code0 {o->flags |= FL_MENU_TOGGLE;} code0 {o->flags |= FL_MENU_TOGGLE;}
} }
MenuItem underline { MenuItem underline {
label {&Underline} label {&Underline}
user_data ADJUST_UNDERLINE user_data ADJUST_UNDERLINE
protected xywh {0 0 34 21} shortcut 0x80075 divider protected xywh {0 0 34 21} labelsize 0 shortcut 0x40075
divider
code0 {o->flags |= FL_MENU_TOGGLE;} code0 {o->flags |= FL_MENU_TOGGLE;}
} }
MenuItem left { MenuItem left {
label {&Left} label {&Left}
user_data ADJUST_LEFT user_data ADJUST_LEFT
protected xywh {0 0 36 21} shortcut 0x8006c protected xywh {0 0 36 21} labelsize 0 shortcut 0x8006c
code0 {o->flags |= FL_MENU_RADIO;} code0 {o->flags |= FL_MENU_RADIO;}
} }
MenuItem right { MenuItem right {
label {&Right} label {&Right}
user_data ADJUST_RIGHT user_data ADJUST_RIGHT
protected xywh {0 0 36 21} shortcut 0x80072 protected xywh {0 0 36 21} labelsize 0 shortcut 0x80072
code0 {o->flags |= FL_MENU_RADIO;} code0 {o->flags |= FL_MENU_RADIO;}
} }
MenuItem center { MenuItem center {
label {&Center} label {&Center}
user_data ADJUST_CENTER user_data ADJUST_CENTER
protected xywh {0 0 36 21} shortcut 0x80063 divider protected xywh {0 0 36 21} labelsize 0 shortcut 0x80063
divider
code0 {o->flags |= FL_MENU_RADIO;} code0 {o->flags |= FL_MENU_RADIO;}
} }
MenuItem {} { MenuItem {} {
label {&Precision...} label {&Precision...}
user_data ADJUST_PRECISION user_data ADJUST_PRECISION
xywh {0 0 36 21} shortcut 0x80070 xywh {0 0 36 21} labelsize 0 shortcut 0x80070
} }
MenuItem {} { MenuItem {} {
label {&Foreground...} label {&Foreground...}
user_data ADJUST_FOREGROUND user_data ADJUST_FOREGROUND
xywh {0 0 36 21} xywh {0 0 36 21} labelsize 0
} }
MenuItem {} { MenuItem {} {
label {&Background...} label {&Background...}
user_data ADJUST_BACKGROUND user_data ADJUST_BACKGROUND
xywh {0 0 36 21} divider xywh {0 0 36 21} labelsize 0 divider
} }
menuitem dec { menuitem dec {
label {&Decimal} label {&Decimal}
user_data ADJUST_DECIMAL user_data ADJUST_DECIMAL
protected xywh {0 0 36 21} protected xywh {0 0 36 21} labelsize 0
code0 {o->flags |= FL_MENU_RADIO;} code0 {o->flags |= FL_MENU_RADIO;}
} }
MenuItem sci { MenuItem sci {
label {&Scientific} label {&Scientific}
user_data ADJUST_SCIENTIFIC user_data ADJUST_SCIENTIFIC
protected xywh {0 0 36 21} shortcut 0x80073 protected xywh {0 0 36 21} labelsize 0 shortcut 0x80073
code0 {o->flags |= FL_MENU_RADIO;} code0 {o->flags |= FL_MENU_RADIO;}
} }
MenuItem cpt { MenuItem cpt {
label {Co&mpact} label {Co&mpact}
user_data ADJUST_COMPACT user_data ADJUST_COMPACT
protected xywh {0 0 36 21} protected xywh {0 0 36 21} labelsize 0
code0 {o->flags |= FL_MENU_RADIO;} code0 {o->flags |= FL_MENU_RADIO;}
} }
MenuItem hex { MenuItem hex {
label {He&xact} label {He&xact}
user_data ADJUST_COMPACT user_data ADJUST_COMPACT
protected xywh {0 0 36 21} divider protected xywh {0 0 36 21} labelsize 0 divider
code0 {o->flags |= FL_MENU_RADIO;} code0 {o->flags |= FL_MENU_RADIO;}
} }
MenuItem shadow { MenuItem shadow {
label {Shadow&ed} label {Shadow&ed}
user_data ADJUST_SHADOW user_data ADJUST_SHADOW
protected xywh {0 0 36 21} shortcut 0x80065 protected xywh {0 0 36 21} labelsize 0 shortcut 0x80065
code0 {o->flags |= FL_MENU_TOGGLE;} code0 {o->flags |= FL_MENU_TOGGLE;}
} }
MenuItem transparent { MenuItem transparent {
label {&Transparent} label {&Transparent}
user_data ADJUST_TRANSPARENT user_data ADJUST_TRANSPARENT
protected xywh {0 0 36 21} shortcut 0x80074 divider protected xywh {0 0 36 21} labelsize 0 shortcut 0x80074
divider
code0 {o->flags |= FL_MENU_TOGGLE;} code0 {o->flags |= FL_MENU_TOGGLE;}
} }
MenuItem lock { MenuItem lock {
label {Lo&ck} label {Lo&ck}
user_data ADJUST_LOCK user_data ADJUST_LOCK
protected xywh {0 0 36 21} shortcut 0x80063 protected xywh {0 0 36 21} labelsize 0 shortcut 0x80063
code0 {o->flags |= FL_MENU_TOGGLE;} code0 {o->flags |= FL_MENU_TOGGLE;}
} }
MenuItem ignore { MenuItem ignore {
label {&Ignore} label {&Ignore}
user_data ADJUST_IGNORE user_data ADJUST_IGNORE
protected xywh {0 0 36 21} shortcut 0x80069 protected xywh {0 0 36 21} labelsize 0 shortcut 0x80069
code0 {o->flags |= FL_MENU_TOGGLE;} code0 {o->flags |= FL_MENU_TOGGLE;}
} }
} }
Submenu {} {label {&Help} open xywh {25 25 67 24}} { Submenu {} {label {Help} open xywh {25 25 67 24} labelsize 0 } {
MenuItem {} { MenuItem {} {
label {&Manual} label {&Manual}
user_data K_HELP user_data K_HELP
xywh {0 0 30 20} shortcut 0xffbe xywh {0 0 30 20} labelsize 0 shortcut 0xffbe
} }
MenuItem {} { MenuItem {} {
label {&About} label {&About}
user_data K_ABOUT user_data K_ABOUT
xywh {0 0 30 20} xywh {0 0 30 20} labelsize 0
} }
} }
} }
Fl_Group line_label { Fl_Group line_label {
label { Input:} open label { Input:} open
protected xywh {0 25 800 25} box ROUND_UP_BOX align 20 deactivate protected xywh {0 9999112 800 9999112} labelsize 9999100
box ROUND_UP_BOX align 20 deactivate
} }
{ {
Fl_Input line_input { Fl_Input line_input {
@ -688,8 +740,12 @@ class MainWindow {open}
line_label->deactivate(); line_label->deactivate();
} }
} }
protected xywh {75 27 723 21} box ROUND_DOWN_BOX protected xywh {75 9999114 723 9999110} box PLASTIC_DOWN_BOX
labelsize 9999100
labeltype NO_LABEL align 20 when 6 deactivate labeltype NO_LABEL align 20 when 6 deactivate
code0 {
line_input->textsize(fontsize);
}
} }
} }
Fl_Box table { Fl_Box table {
@ -773,14 +829,15 @@ class MainWindow {open}
case FLT_NO_FORMAT: ; case FLT_NO_FORMAT: ;
} }
} }
protected xywh {0 50 800 525} box DOWN_FRAME protected xywh {0 9999224 800 99990336} box DOWN_FRAME
labeltype NO_LABEL resizable labeltype NO_LABEL resizable
code0 { table->sheet(sheet); } code0 { table->sheet(sheet); }
class TeapotTable class TeapotTable
} }
Fl_Box status { Fl_Box status {
label {teapot ready.} label {teapot ready.}
protected xywh {0 575 800 25} box GTK_ROUND_DOWN_BOX align 20 protected xywh {0 99990112 800 9999112}
box GTK_ROUND_DOWN_BOX align 20
} }
} code { } code {
current = this; current = this;

39
src/tools/interpolate.py Normal file
View File

@ -0,0 +1,39 @@
# To get around the fact that fluid only allows numerical constants
# in some places that expressions would be preferred, this
# file takes a fluid file which may contain numerical constants of the form
#
# 9999NNN/*REPLACEMENT*/
#
# where the NNN are distinct digit sequences (of any length)
# and the corresponding fluid output and replaces any 9999NNN in the output
# with REPLACEMENT (which can of course be any text). Note that the
# entire numerical constant with its replacement comment must occur within
# a single line of the fluid file. The result is written
# to a new output file with the literal string `_interpolated` interpolated
# before its extension.
from pathlib import Path
import re
import sys
fluidin = sys.argv[1]
genfile = Path(sys.argv[2])
outfile = genfile.with_stem(genfile.stem + '_interpolated')
# First collect all of the replacements from the fluidfile
replacerPattern = re.compile(r"(9999\d*)/[*](.*)[*]/")
replacement = {}
with open(fluidin) as fluidf:
for line in fluidf:
foundpat = replacerPattern.search(line)
if foundpat:
replacement[foundpat[1]] = foundpat[2]
# Now make all replacements in the generated file
with open(outfile, 'w') as outf:
with open(genfile) as genf:
for line in genf:
line = line[:-1]
for key in replacement:
line = line.replace(key, replacement[key])
print(line, file=outf)

View File

@ -62,6 +62,8 @@ Display strings definitely NOT quoted or definitely quoted, respectively.
Redraw the terminal window more often. Redraw the terminal window more often.
.It Fl p Ar digits .It Fl p Ar digits
Set default precision of displayed numbers. Set default precision of displayed numbers.
.It Fl F Ar digits
Set the general font size on pixels (fteapot only).
.El .El
.\" .\"
.\" .\"