Previous | Contents | Next


Appendix A - Miscellaneous

A.1 Shortcuts

A.1.1 Keyboard Shortcuts

Several of the menu options have keyboard shortcuts which are labelled next to the option. In addition to these facilities, there are further shortcuts that you may find useful. This first table lists shortcuts that are available when the focus in on the sheet (such as when you start mtCellEdit).

Home Move to column 1 in the current row
Home + CTRL Move to the row 1 column 1 cell
End Move to the last column in the current row
End + CTRL Move to the last column and the last row
Page Up Scroll the sheet a page up
Page Up + ALT Scroll the sheet a page left
Page Down Scroll the sheet a page down
Page Down + ALT Scroll the sheet a page right
Arrow keys Move the selection to another cell
Arrow keys + SHIFT Change the currently selected area
Arrow keys + CTRL Move to the next active row (in the sheet) or column (in this row)

This table lists the keyboard shortcuts you can use when you are editing the cell text in the cell entry box:

Escape Cancel current operation
Enter/Return Set cell text and move the cursor down one cell
Tab Set cell text and move the cursor right one cell
Tab + CTRL Set cell text and move the cursor left one cell
Up/Down Arrow Key Set cell text and move the cursor up or down one cell

All of these actions are then following by the focus moving to the sheet again. The Escape key also returns focus to the sheet while editing the cell range box or editing the graph text.

A.1.2 Mouse Shortcuts

Left button Select a cell or area (clicking or dragging). When the cursor focus is in the cell entry box, a left click puts a cell reference into the entry (SHIFT=absolute row; CTRL=absolute column).
Right button Select the second corner of an area (clicking or dragging). When the cursor focus is in the cell entry box, a right click puts a ':' character and the cell reference into the entry (SHIFT=absolute row; CTRL=absolute column).

A.2 Supported File Types

CED Load/Save mtCellEdit book of sheets and their preferences. Each CED file is a ZIP archive containing TSV or Ledger files, and preferences information.
TSV Load/Save Tab Separated Values (single sheet) Up to 1,000,000 rows, 1,000,000 columns, covering at most 1,000,000,000 cells.
Ledger Load/Save A ledger of all cell content (single sheet) Up to 1,000,000,000 rows and columns.
CSV Load/Save Comma Separated Values (single sheet) Up to 1,000,000 rows, 1,000,000 columns, covering at most 1,000,000,000 cells. When loading a file, if its name ends with .csv (case insensitive), it is assumed to be a CSV file, with all other files being TSV.

A.2.1 CED Files

A CED file is in fact a ZIP archive file. You can use whatever file extension you like. I chose the ZIP archive format because it can be opened using any operating system, thus allowing anyone to open the collection of sheets easily and independently of the mtCellEdit program. The ZIP archive contains files in the following form:

Internal Filename Description
filename/sheet/* Each sheet in the book is stored here as a TSV/Ledger file, with its name being in place of *.
filename/values/* This is an optional section used when saving the values within the CED file. The purpose of saving cell values is: (*) It is useful for archiving purposes as the data can be read by any spreadsheet program because no formulas are saved as they are replaced by the numerical values. (*) Complex sheets with convoluted cell relationships do not require numerous recalculations between sessions to get correct values (mtCellEdit uses a very simple top-down bottom-up recalculation algorithm that can be tricked when using several forward/backward references in sheets).
filename/graph/* This is where the text for each graph is stored.
filename/prefs/book.txt This file contains book, sheet, and cell preferences. By keeping this data separate from the sheet data it makes it much easier to transfer the sheet data to other spreadsheet programs.

In all cases 'filename' is the name of the original file saved, so this would be 'test' if you saved 'test.zip'. On loading, any other file is ignored, but is stored in memory so when the book is saved again these files will be retained in the new CED/ZIP file (with the same time and date stamps).

A.2.2 TSV Files

A TSV file (Tab Separated Value) is my preferred file format for sheets as it can be read by any good spreadsheet program. I prefer it over CSV because its simpler. The CSV format has the major flaw that commas can be used in a cell thus complicating the encoding of each cell text (i.e. the inefficient " quotation system). TSV files are simpler as the tab character is never used in a cell, and therefore its much quicker to parse this file format than any other encoding.

A.2.3 Ledger Files

Ledger files are designed for the very rare occasion when you have a very large but sparse sheet, such as 10,000 cells of content within a 1,000,000,000 x 1,000,000,000 sheet. Saving this to a TSV or CSV file would be grossly inefficient because of the duplication of empty cells. The down side of using ledger files is that the format cannot be read by other spreadsheet programs.

A.2.4 CSV Files

Despite being widely used, the CSV file format has no official specification, and sadly this means that different programs create slightly different CSV files. As a result of this some files may not load properly into mtCellEdit (or other spreadsheet programs). However, mtCellEdit should load all RFC-4180 compliant files as long as they don't contain newlines inside a field.

A.3 Functions

A function returns a number. Valid function syntax is:

function_name( [ARG]... )

Arguments are separated by a , or ; character.

A NUM is a decimal number, a function, or a CELLREF. A STRING is a collection of characters with " quotes, e.g. "Hello".

A CELLREF takes the r1c1 notation, e.g.

r1c1 Absolute reference.
r[-1]c[-1] Relative reference.
r_c_ _ is a shorthand for the maximum row/column number.

A RANGE takes the form:

CELLREF:CELLREF

Cells and ranges in other sheets can be referenced by using:

'sheet_name'r1c1

Here is a complete list of functions mtCellEdit understands when placed after an = character in the cell text:

Function Arguments Description
abs NUM Absolute value. e.g. abs(-2) = 2
acos NUM Inverse cosine
asin NUM Inverse sine
atan NUM Inverse tangent
atan2 Inverse tangent (two arguments)
NUM x
NUM y
average RANGE Calculate average of all numbers in the range
ceil NUM Round a decimal number up. e.g. ceil(2.1) = 3
cos NUM Cosine
cosh NUM Hyperbolic cosine
count RANGE Count the number of cells with numbers (i.e. ignore text and errors)
counta RANGE Count non-empty cells
countblank RANGE Count empty cells
countif Count the number of numerical cells that pass a test
RANGE Range of cells to check
STRING Conditional test "<" "<=" ">" ">=" "=" "<>"
NUM Number to test each cell in the range with
date Get numerical representation of a date. date( 0, 1, 1 ) = 0
NUM Year 0..5879609
NUM Month 1..12
NUM Day 1..31
day NUM Return day of month of a given numerical date
degrees NUM Converts a radian number to degrees
exp NUM Raise e to the power of NUM
fact NUM Return factorial of NUM when 0 <= NUM <= 170
floor NUM Round a decimal number down. e.g. floor(2.1) = 2
frac NUM Return the fractional part of a decimal. e.g. frac( -1.234 ) = -0.234
hour NUM Return the hour of a date/time number 0..23
if e.g. if( 1, 2, 3 ) = 2; if( 0, 2, 3 ) = 3; if( 1<2, 2, 3 ) = 2
NUM 0=FALSE else TRUE
NUM Returned if TRUE
NUM Returned if FALSE
int NUM Rounds down to the nearest integer
large Return the largest number in the range as per rank
RANGE
NUM Rank (1=largest 2=2nd largest, etc.)
ln NUM Natural logarithm
max RANGE or NUM Return the maximum number from the range(s), or the number(s).
... You are allowed to enter up to 10 function arguments.
median RANGE Return the median number in the range
min RANGE or NUM Return the minimum number from the range(s), or the number(s).
... You are allowed to enter up to 10 function arguments.
minute NUM Return the minute of a date/time number 0..59
mod Return modulo of a number. e.g. mod( 5, 2 ) = 1
NUM Number
NUM Modulo
month NUM Return the month of a date/time number 1..12
now Return the current date/time number
offset Return the value in another cell via an offset
#CELLREF Start
NUM Rows offset from CELLREF
NUM Columns offset from CELLREF
percentile Return the given percentile of the range.
RANGE
NUM Percentile 0.0 .. 1.0
percentrank Return the percentage rank of the number given. 0.0 .. 1.0
RANGE
NUM This must be >= to the minimum and <= to the maximum number in the range
pi PI
radians NUM Converts a degree number to radians
rand Random number
rank Return the rank of a given number. 1=lowest/highest.
NUM Number (must be in RANGE somewhere)
RANGE
NUM 0=lowest 1=highest
rgb Return a packed RGB number.
NUM 0..255
NUM 0..255
NUM 0..255
round NUM Round this numbers digits.
NUM 0 rounds at decimal point, <0 rounds to the left of the decimal point by that number of digits, >0 rounds to the right of the decimal point by that number of digits.
second NUM Return the seconds of a date/time number 0..59
sin NUM Sine
sinh NUM Hyperbolic sine
small Return the smallest number in the range as per rank.
RANGE
NUM Rank (1=smallest 2=2nd smallest, etc.)
sqrt NUM Square root
strvlookup Look up a string in a range, and return a value from another cell in that row.
#CELLREF Text to find is in this cell
RANGE Range to scan for text
NUM Column index offset, relative to RANGE. 1=first column to right of RANGE
sum RANGE Sum all numbers in the range
sumif Sum the contents of numerical cells that pass a test.
RANGE Range of cells to test
STRING Conditional test "<" "<=" ">" ">=" "=" "<>"
NUM Number to action the test on
#CELLREF Top left cell of sum range
tan NUM Tangent
tanh NUM Hyperbolic tangent
time Get numerical representation of a time. time( 0, 0, 0 ) = 0.0; time( 12, 0, 0 ) = 0.5
NUM Hours
NUM Minutes
NUM Seconds
today Return today's date number
trunc NUM Truncate this numbers digits.
NUM 0 truncates at decimal point, <0 truncates to the left of the decimal point by that number of digits, >0 truncates to the right of the decimal point by that number of digits.
vlookup Look up a value in a range, and return a value from another cell in that row.
NUM Number to find
RANGE Range to scan for 'NUM'
NUM Column index offset, relative to RANGE. 1=first column to right of RANGE
weekday NUM Return the weekday of a date/time number. 1..7
year NUM Return the year of a date/time number

A.4 Cell Formats

One of the cell preferences is the 'format' which determines how the cell is rendered. By choosing a different format and adjusting other cell preferences the output can be tailored as required.

Format Preferences Description
General format_datetime Render a cell according to its internal type as determined by the parser. This could be a number, text, a date, etc.
num_thousands
Text - Render the exact text in the cell.
Fixed Decimal num_decimal_places Render a decimal number according to the number of prescribed decimal places.
num_thousands
Hexadecimal num_zeros Render a hexadecimal number, with the option of padding for leading zeros.
Binary num_zeros Render a binary number, with the option of padding for leading zeros.
Scientific num_decimal_places Render a number using scientific notation for a prescribed number of decimal places.
Percentage num_decimal_places Render a number as a percentage, with 1.0 being 100.0%
num_thousands
Datetime format_datetime Render a number as a date and time according to a prescribed form.

The format_datetime text string expands the following special characters:

d Day number.
dd Day number with a leading zero.
ddd Day name, abbreviated.
dddd Day name, full.
m Month number.
mm Month number with a leading zero.
mmm Month name, abbreviated.
mmmm Month name, full.
y Year number.
yy Year number (2 digits) with a leading zero.
H Hour number.
HH Hour number with a leading zero.
M Minute number.
MM Minute number with a leading zero.
S Second number.
SS Second number with a leading zero.
\ Render the next character as itself. This allows the rendered text to include the d m y H M S \ characters.

All other characters encountered are directly placed into the rendered string.

A.5 Error Codes

When the parser finds an error it displays an error in the form:

Err:x,y

The y represents the number of characters that were parsed before the error occurred. The x represents the error itself as described in this table:

0 Syntax error
1 Memory error
2 Bad function name
3 Bad function token
4 Bad function argument
5 Bad function operation
6 Bad number
7 Bad sheet reference
8 Infinity
9 Not a number
10 Bad cell reference
11 Cell text too long

A.6 Limitations

As with all software, mtCellEdit has some limitations. In some cases any attempt to overcome these limitations would invalidate the purpose and philosophy of the project. Therefore I am documenting these limitations in order to explain the policy decisions I have taken. However, mtCellEdit is free software so if anyone disagrees then they are free to fork the code and implement their own ideas.

A.6.1 Localization

mtCellEdit is entirely written in English, with all language and numerical notation being geared towards that locale. There are many different languages and numerical systems that could be supported by a spreadsheet program, but to do so would complicate the program and the data files that the program creates.

For example, one of the rules I insist on with mtCellEdit is whatever text the user enters into a cell this must be exactly what gets recorded in the saved file. I have a particular dislike of programs that subvert user input via optimizations, or corrections (such as removing spaces in formulas or capitalization of certain letters).

This causes a problem when saving data to a TSV file and moving the data between locales that use a different decimal point system. For example if I have a TSV file with 1.23 in it, my English locale will interpret that as a decimal number. However in a French locale this would not be recognised as a number and would be treated as a text string. Naturally the reverse would also be true with 1,23 being a decimal number in the French locale but not the English locale.

In other words we have a problem regarding data portability and non-deterministic program behaviour. From version 1.4.0 of mtCellEdit I avoided this problem by enforcing a C locale when the program starts, so all data is interpreted using the same standards whatever locale the operating system happens to be using. When not using the GUI and using libmtcelledit directly the calling program will need to set the locale to 'C' otherwise there may be problems.

Another example of localization regards right to left rendering of cells, and the use of exotic fonts and various font substitutions. Even if I had the time and expertise to implement such features, this would dramatically bloat the program, and complicate many parts of the program structure.

Because of these issues, I have decided to keep mtCellEdit a solely English locale project. I do not have the time or inclination to change this.

A.6.2 Spreadsheet File Formats

I have deliberately chosen to not support mainstream file formats for other spreadsheet programs as they are reliant on complex binary or XML files. I have seen these various formats come and go over the years as the programs that use them become popular, and then fade into obscurity. In the beginning the 'industry standard' program was Visicalc, then Lotus 1-2-3, and most recently Excel. Each program has also adopted various major revisions to its file format over its lifetime, which makes data portability even more of a problem.

Due to the policy decisions of the creators, those 'industry standard' programs are continuing to use data formats that will not stand the test of time, and are a bad choice as a data archive format. Therefore I refuse to support them, and this is why I prefer to use simple text based formats instead. Somebody using the Awk program on a Unix system in 1980 could easily manipulate a TSV file, as they can today, and as they will be able to do for decades to come. In other words this file type is built to stand the test of time, and is therefore the best choice as an archive format.

In short, mtCellEdit has never, and will never support binary or XML based data files.

A.6.3 Dates

The year in a date is only valid from 0 to 5879609.

All years are interpreted literally, so an abbreviated two digit year is considered different to a four digit year. For example 25/10/12 is not the same as 25/10/2012. This strictness avoids ambiguity and problems like the millennium bug.

If you encounter a datafile which contains a two digit year that you wish to convert to a four digit year you would do the following:

  • Select the relevant cells you want to change.
  • Select the menu option "Edit - Fix 2-digit Years"

By default this assumes the years are to be changed to some time in the last 50 years or the coming 49 years. If you want to change the start year to something else you must change the Program Preference "date.2digit_year_start".

A.6.4 Numbers

Each cell contains a number which is stored internally as a double precision floating point number. Typically this means it is accurate to 15 significant decimal digits.

When displaying this number as a binary or hexadecimal number the accuracy is about 52 bits.

A.7 Graph Language

Graphs are defined in a block of text using my own data language called utree (which is part of libmtKit). Here is a simple example which illustrates how to use instructions that contain various attribute values, with various useful comments:

/*
	This is a comment - it can contain any text.
*/


{ instruction_name
	attribute="value"
	another_attribute="value"
	"This contains spaces"="Backslashes and quotations must be backslashed first: \\ and \" - easy isn't it!"

	sheet="Sheet Name"
/*
	Normally attribute values are only used in the instruction that defines them.
	However, the 'sheet' attribute value is special as it is used by all subsequent
	instructions until it is re-defined.
*/

}

{ another_instruction

/*
	Comments can appear anywhere.
	This instruction contains no attributes, so the default values are used.
	See below for a complete list of default attribute values.
*/

}

All attribute values are considered as double precision floating point numbers unless otherwise stated below. You can use spreadsheet notation and functions such as "2.0 + 2.1", "2011-10-9", "rgb(1,2,3)", "0xFFAA11" or even use cell references (use this wisely as the sheet attribute must be set properly).

A.7.1 Conceptual Outline

The general sequence of a graph should follow this pattern:

  • Define the page, graph, and plot areas.
  • Define the X and Y axis.
  • Plot the axis text and markings. (OPTIONAL)
  • Plot any gridlines that appear beneath the graphs. (OPTIONAL)
  • Plot the shapes and lines using data from a sheet. (OPTIONAL)

Any number of graphs and gridlines can be used, each with their own X and Y axis settings.

A.7.2 Page Layout

The page is initially defined as a physical width and height, with the origin of (0,0) being at the top left corner. Each unit is 1/72 of an inch. This page contains a 'graph' rectangle which itself contains a 'plot' rectangle which is used to do all of the final plotting on using the logical X and Y axis settings as prescribed.

The 'graph' area contains top, bottom, left and right axis titles, with additional text labels and axis markings (all optional).

A.7.3 Graph Instructions and Attributes

Here is a table with a list of instructions and attributes that they use. In addition, all drawing or plotting instructions (i.e. page, graph, plot, plot_*) will be affected by:

  • antialias
  • arrowhead
  • fill_color
  • line_color
  • line_size
  • text_color
  • text_size
Instruction Attributes Used Notes
graph x_pad These attributes are in physical points. The padding is the gap between the outer graph rectangle and the plot rectangle.
y_pad
page height These attributes are in physical points. The padding is the gap between the outer page and the graph rectangle. This should always be the first instruction. Although the sheet attribute isn't required here, it can be useful to define it here if only one sheet is to be used as a data source. By doing this you avoid the need to keep defining it later.
width
x_pad
y_pad
plot x_pad These attributes are in physical points. The padding is the gap between the outer plot rectangle and the inner plot rectangle. In other words the total gaps between the outer graph rectangle and the outer plot rectangle is the sum of the two pads defined in both instructions.
y_pad
plot_box data data points to a range of cells (e.g. r1c1:r_c1). These are parsed top down with 5 columns for x1, x2, y1, y2, text. The coordinates relate to the logical coordinates in the plot area and are clipped to that rectangle. Text (if present) is rendered inside the box at the prescribed settings.
plot_ellipse data data as plot_box. Text (if present) is rendered inside the ellipse at the prescribed settings.
plot_graph_bar data data points to a single line (horizontal or vertical) of cells, such as r1c1:r1c_. These cell values are used to draw the graph in the plot area. The values are interepreted as Y coordinates, with X starting at the x_axis minimum, and incremented according to gap.
gap
plot_graph_line data data as plot_graph_bar
gap
plot_line data data as plot_box. Text (if present) is rendered at the end of the x2, y2 coordinate. If the arrowhead value is greater than 0 this is rendered at the end of the x2, y2 coordinate.
plot_x_axis data If data is used then this is a horizontal or vertical set of cells that are used to label each axis mark.
gap
label_format If label_format is set then use this as a sheet cell reference to render the numbers in this form.
size If size is defined draw marks along the axis at gap intervals.
text If text is defined, draw the axis title as this, with the prescribed justification.
x_justify If you plan to use titles and axis labels of simultaneously it is wise to have two instructions for this: one for the title and one for the labels, so that the text sizes and justifications don't clash.
y_justify
plot_x_axis_grid gap Draw horizontal lines across the plot area parallel with the X axis at intervals defined by gap.
min min can be used to shift the modulo origin to something other than 0, which is useful if the axis doesn't begin at 0.
plot_x_axis_top as plot_x_axis as plot_x_axis
plot_y_axis as plot_x_axis as plot_x_axis
plot_y_axis_grid gap Draw vertical lines across the plot area parallel with the Y axis at intervals defined by gap.
min min can be used to shift the modulo origin to something other than 0, which is useful if the axis doesn't begin at 0.
plot_y_axis_right as plot_x_axis as plot_x_axis
x_axis min This sets the logical limits of the plot area. If min is greater than max then the direction of the plotting and the axis is reversed, i.e. from right to left.
max
y_axis min This sets the logical limits of the plot area. If min is greater than max then the direction of the plotting and the axis is reversed, i.e. from bottom to top.
max

A.7.4 Default Attribute Values

Attribute Value Notes
antialias 1 This only affects bitmap rendering. 0=Don't antialias; 1=Do.
arrowhead 0 At values greater than 0 an arrowhead is drawn with this size at the end of each line.
data NULL Text string. This is usually a cell range for the graphs.
fill_color 0xFFFFFF When greater or equal to 0 fill using this colour. Otherwise don't fill.
gap 0
line_color 0 When greater or equal to 0 draw lines using this colour. Otherwise don't draw anything.
line_size 1 Lines are drawn with this thickness.
max 0
min 0
sheet Inherited Text string set to NULL at first. This is the only default attribute that is inherited from the previous instructions. This should contain text that refers to a sheet in the book. If this sheet doesn't exist, its reference is cleared to NULL.
size 0
text NULL Text string.
text_color 0 When greater or equal to 0 draw text using this colour. Otherwise don't draw anything.
text_size 12 Font size in units.
x_justify 0.5 0=Justify to the left; 0.5=Centralize; 1.0=Justify to the right.
x_pad 0
y_justify 0.5 0=Justify to the top; 0.5=Centralize; 1.0=Justify to the bottom.
y_pad 0

A.8 Preferences

Preferences are held in memory as per the C structures defined in the source code. They are also held in CED/ZIP files as explained in A.2.1.

A.8.1 Cell

Key Data Notes
align_horizontal INTEGER 0=None, 1=Left, 2=Centre, 3=Right
text_style INTEGER Bit field
border_color INTEGER Packed RGB 0xRRGGBB
border_type INTEGER Bit field
color_background INTEGER Packed RGB 0xRRGGBB
color_foreground INTEGER Packed RGB 0xRRGGBB
format INTEGER 0=General, 1=Text, 2=Fixed Decimal, 3=Hexadecimal, 4=Binary, 5=Scientific, 6=Percentage, 7=Datetime
format_datetime STRING
locked INTEGER 0=Unlocked, 1=Locked
num_decimal_places INTEGER
num_thousands STRING Thousands separator character
num_zeros INTEGER Pad with leading zeros in binary and hexadecimal cell formats
text_prefix STRING
text_suffix STRING
width INTEGER Only used in row 0 for setting column width

A.8.2 Sheet

Key Data
cursor_c1 INTEGER
cursor_c2 INTEGER
cursor_r1 INTEGER
cursor_r2 INTEGER
locked INTEGER
split_c1 INTEGER
split_c2 INTEGER
split_r1 INTEGER
split_r2 INTEGER
start_col INTEGER
start_row INTEGER

A.8.3 Book

Key Data Notes
active_graph STRING
active_sheet STRING
author STRING When creating a new book, this is populated with the users name (from the operating system)
auto_recalc INTEGER 0=None, 1=Sheet, 2=Book
comment STRING
disable_locks INTEGER 0=Enable Locks in sheets/cells, 1=Disable Locks in sheets/cells

A.8.4 State

The state is an area in mtCellEdit and mtCedCLI that stores information regarding the page for exporting the sheet to a paged PDF. mtCellEdit stores changes to this information in the ~/.mtcelledit preferences file for each session, whereas mtCedCLI always starts each session with the defaults.

Key Data Default Notes
page_font_size INTEGER 10
page_footer_centre INTEGER 0 0=None, 1=Filename (long), 2=Filename (short), 3=Sheet Name, 4=Page Number, 5=Date, 6=Date and Time
page_footer_left INTEGER 6 0=None, 1=Filename (long), 2=Filename (short), 3=Sheet Name, 4=Page Number, 5=Date, 6=Date and Time
page_footer_right INTEGER 4 0=None, 1=Filename (long), 2=Filename (short), 3=Sheet Name, 4=Page Number, 5=Date, 6=Date and Time
page_header_centre INTEGER 0 0=None, 1=Filename (long), 2=Filename (short), 3=Sheet Name, 4=Page Number, 5=Date, 6=Date and Time
page_header_left INTEGER 2 0=None, 1=Filename (long), 2=Filename (short), 3=Sheet Name, 4=Page Number, 5=Date, 6=Date and Time
page_header_right INTEGER 3 0=None, 1=Filename (long), 2=Filename (short), 3=Sheet Name, 4=Page Number, 5=Date, 6=Date and Time
page_margin_x INTEGER 10
page_margin_y INTEGER 10
page_mm_height INTEGER 210
page_mm_width INTEGER 297

A.9 File Handling

When editing a file in mtCellEdit the titlebar describes the file IO permission via a code:

{} Book has no filename yet.
{RW} File is Read/Write (i.e. any other program can write to it).
{RWL} File is Read/Write and Locked against other programs writing to it via a temporary read only file permission on disk.
{RO} File is Read Only and cannot be saved using this filename.

At all times you can edit the book in memory but you can only save using the current filename if a W is present in the title bar.

A.9.1 File Locks (RWL & RO)

By default mtCellEdit loads data from a file and edits this in memory until the user saves the data. This is pefectly reasonable under most circumstances, but occasionally this is unsafe such as when an absent minded user accidentally opens the same file in two mtCellEdit instances. If the user has unsaved data in instance 1, and then loads the same file into instance 2, these changes will not appear in instance 2. If the user was to make changes in instance 2 and save those changes this could create real confusion and potentially lose data.

In order to avoid such problems between mtCellEdit instances, or even other programs editing files, you can switch on a locking mechanism which switches off the write permissions on the file while it is being edited. Then other programs are stopped from making changes until mtCellEdit finishes editing it and the original file permissions are restored.

In the program preferences, filter for 'lock' and you should find:

file_lock_load
file_lock_save

Switch both to RWL and then every time you load and save a file a Re-Write Lock is enabled. Then any other program, including multiple mtCellEdit instances, cannot modify the file while it is still being edited by the original mtCellEdit instance.

You can also force all files to be Read-Only after loading or saving if that suits your needs.

If you have the {RWL} setting on, it may fail under a specific circumstance and be {RW}. This happens when a user has permission to write to the file but is not able to change the write permission to get a lock. If this is because another user owns the file, or you are not in the correct file group, you can simply save the file to get {RWL} locking enabled which changes the ownership of the file.

A.9.2 Saving (Temporary File)

In mtCellEdit and mtCedCLI, when saving a file to disk a temporary file is used to initially write the data to. This is to protect against power failure, OS failure, hardware failure, etc causing the original file data to be lost before the new data is saved. Once the temporary file has been successfuly saved it is renamed to the designated filename to complete the operation.

A.10 Historic Design Choices

When I first started the mtCellEdit project, some design decisions were forced on me by the limited hardware and software available at the time. As things changed over time I was able to improve the project by taking advantage of improvements to hardware such as faster devices. Likewise, the software that mtCellEdit relies on has also changed. For example when I started I used GTK+ version 2, which continued until 2016 when I switched over to using Qt version 5 by default.

A.10.1 Font Rendering

During 2010-2016, versions 1.0 to 2.6 of mtCellEdit rendered text directly using FreeType or a hard coded ASCII font, which was the fastest method available and was desirable on slower hardware manufactured before 2005. However, by 2016, even cheap PC hardware was fast enough to comfortably use Pango to render fonts with nice luxuries such as kerning and font substitution. By 2022 and version 3.6, I started using Cairo to render what appeared on screen which enables luxuries such as multicoloured emojis on many systems, such as 💯 and 🤩. PC hardware manufactured after 2014 should have enough speed to do this efficiently (as proven by a cheap PC such as the Raspberry Pi). A user preference can be selected to change the screen rendering back to Pango (main_window_renderer) if the user wants things rendered slightly faster.


Previous | Contents | Next