martes, 15 de julio de 2008

Nuevo formato de KeyNote

El formato de un fichero KeyNote se ha ampliado algo:

KEYNOTE 1.7: File Format Specification
Last updated: 30 November 2007

New elements added are marked with [dpv]

KEYNOTE 1.x: File Format Specification
Last updated: 12 June 2003

KeyNote uses plain text files which can be read on a line-by-line basis.
RTF data is stored as-is, without any conversion.

The file consists of a header section and a data section.

The header identifies the file as a valid KeyNote file and stores some metainformation about the file, such as the date and time the file was created, which note was last active, user-defined description and comment, etc.

The data section consists of subsections for notes and tree nodes. Sections and subsections are separated by special markers, described below.

Almost all elements in the data section, where the properties of notes and tree nodes are stored, are optional. KeyNote fills in any missing data using default values. This applies even to names of notes. Default values are configured by user via Tools|Default settings. There is a bug, however, which prevents KeyNote from automatically assigning default names for tree nodes, so if a particular tree node has no name specified in the file its caption will be blank. Other than that, you can leave out all elements of a file. Only the markers are required, because they define the structure of the file.

For tree nodes, the level number must also be specified, because it is required to re-create the tree hierarchy: level value indicates nesting, where level value of zero means top-level (root) node.

Some elements or identifiers mentioned in this document may not appear in every KeyNote file. This is because some elements are only stored in the file if necessary. For instance, the file header carries information about the note which was used for clipboard capture. If clipboard capture was not enabled at the time the file was saved, this property is not stored in the header.

(The example elements and properties shown in this document are based on a sample file "fileformat.knt", included in the package. The file contains one simple note with two lines of text, and one tree-type note with two normal nodes and one virtual node.)

This document does not describe the structure of encrypted files, because this is closely tied to the encryption library used (DCPCrypt 1.0, by David Barton). Please see KeyNote source code to see how encrypted files are created and handled.

Full KeyNote source code and other information is available at:

Marek Jedlinski



Each line begins with '#', followed by a single character that identifies a header field. All header fields except for the first line are optional and will be auto-created if missing (KeyNote will use default values). The first line identifies the file as a valid KeyNote file and MUST be present. Lines not understood are simply ignored, as long as each line begins with the '#' character.

Header ID - required; must not be changed. (1.0 was used for files that did not have tree-type notes.)
#!GFKNT 2.0

Comment line, ignored
# This is an automatically generated file. Do not edit.

Optional: user-defined file description (single-line)
#/This is the optional description

Optional: user-defined comment (single-line)
#?This is the optional comment

Optional: Number of "active" note (zero-based)

Optional: Date and time the file was created
#C21-05-2003 15:24:50

Optional: "Flags" string - see Notes, below.

Optional: icon file to use for tray icon

Optional: external file where tab icons are stored

Optional: if clipboard capture was active at the time the file was saved, this is the index of the note which was used for clipboard capture



The start of each subsection is marked by a single line. The first character in such lines is always the percent sign. For example, '%' marks the start of a new simple note, while '%+' marks the start of a tree-type note. Markers are as follows:

marks start of a new SIMPLE note

marks start of a TREE-TYPE note

marks start of NODE in a tree-type note

marks start of RTF data. Please see below for notes about the RTF data section.

marks end of file (KeyNote stops reading the file here, but it will also stop at end of file, so this marker is not required, though always present in files generated by KeyNote.)

No other markers are used. No end-of-section markers are used, except for end-of-file, above.


Each line begins with a 2-character identifier, possibly followed by equal sign (=) and data. For example,
identifies the note name.

Each line is guaranteed to be at least one character long. Each line with an identifier is guaranteed to be at least three characters long: the two characters of the identifier itself, plus the equal sign. (The file can be analyzed a little faster if we don't have to check for zero-length strings.)

Note name
NN=Simple note

Unique note ID (integer, auto-created if missing)

Note icon index (index for the icon displayed on the note's tab)

Date and time the note was created
DC=21-05-2003 15:25:25

Index of the note's tab (i.e., the order of the node)

Tab size (as defined by user in Note Properties)

Caret position (SelStart, zero-based)

Selection length (SelLength; 0 if no text is selected)

Note background color

Default font character set for note

Default font color for note

Default font name for note
FN=Courier New

Default font size for note

Default language for note

Default font style for note (can include strings: 'bold', 'italic', 'underline', 'strikeout')
ST=bold italic

Flags string (see Notes, below)

Number of lines of text (not required, but allows KeyNote to pre-allocate memory, which somewhat improves the speed of loading data into the RTF editor)

RTF data marker, followed by RTF data until one of the following occurs: new note start, new tree node start, end of file.
{\rtf1\ansi\ansicpg1250\deff0\deflang1045{\fonttbl{\f0\fnil\fcharset238{\*\fname Courier New;}Courier New CE;}{\f1\fnil\fcharset0 Courier New;}}
{\*\generator Riched20;}\viewkind4\uc1\pard\f0\fs24 This is the text of the simple note.\par
This is another line of text.\par

New TREE NOTE starts:

Note name
NN=Tree note

Unique note ID

Other identifiers already described above:
DC=21-05-2003 15:24:50
FN=Courier New

Index of currently selected tree node

Width of the tree panel, in pixels

Default name for new nodes
EN=New node

Tree panel background color

Tree font character set

Tree font color

Tree font name

Tree font size

Tree font style (format as above: bold, underline, italic, strikeout)

New TREE NODE starts

Node level (indicates nesting)

Node name (caption)
ND=This is a node

Unique node ID

Node flags string (see Notes, below)

Background color for text of the node (editor, not tree color)

Optional: Color for node caption text (see also node flags)

Optional: Background color for node caption (see also node flags)

Optional: Font name for node caption (see also node flags)

Optional: Caret position (zero-based)

Optional: Node image index (if "custom icons" are selected for the tree)

Optional: Alarm instant (New in 1.7.1) [dpv]
NA=21-05-2007 15:24:50

Optional: relative path to file, if node is a virtual node

Optional: full absolute path to file, if node is a virtual node (see also node flags)

RTF data follows:
{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset238{\*\fname Courier New;}Courier New CE;}{\f1\fnil\fcharset0 Courier New;}}
{\*\generator Riched20;}\viewkind4\uc1\pard\lang1045\f0\fs24 This is the text of the node.\par
This is another line of text.\par

End of fie marker follows:



1. About "flags" strings.

Flags strings hold a number of boolean (yes/no) values, and, rarely, other types of values. Each value is encoded as a single character in the flags string. Boolean values are encoded as 0 (false) and 1 (true); for meaning of other values see flag descriptions below.

Each flag string is exactly 24-characters long, and will be IGNORED if it is shorter. (That is, if the string is shorter than 24 characters, KeyNote will not read ANY values from the string.) Not all 24 values are used.

There are three versions of the flags string: one for file, one for each note (with additional meanings for tree-type notes), and another one for every node in the file.

The meanings of particular flags and values have changed with subsequent releases of KeyNote. Only the current values and meanings are described here - they are valid for KeyNote 1.6. If your file was created by an older version, the meaning of some flags may be different than described here.


position type meaning
1 boolean Open file as read-only
2 boolean Show icons on tabs
3 boolean TRUE if file was saved using version 3.0 of the richedit control; otherwise FALSE
4 boolean TRUE if the multi-level backup setting (Tools|Options) should be IGNORED for this file; otherwise FALSE (i.e. perform multi-level backup if so configured)
(other flags are unused)

- flags for simple notes:

position type meaning
---------- -------------- --------------
1 boolean Note is visible
(UNUSED; could be used for hiding notes, but this has never been implemented)
2 boolean Note is read-only
3 boolean Word-wrap ON/OFF
4 boolean URL detection ON/OFF
5 boolean if TRUE, use true TAB character in this note;
if FALSE, insert spaces instead of TAB character when user presses the TAB key
6 boolean if TRUE, note has the "Plain text only" setting enabled (Note properties|Advanced). IMPORTANT: This affects how RTF data is stored, see below.

- additional flags for tree-type notes:

position type meaning
---------- -------------- --------------
13 integer Tree icons selector: 0 = No icons; 1 = Standard (default) icons; 2 = Custom icons
14 boolean Automatic node numbering ON/OFF
(if TRUE, node number is automatically added to node name when node is created)
15 boolean Show checkboxes in tree ON/OFF
16 boolean TRUE = vertical tree layout; FALSE = horizontal tree layout
17 boolean TRUE = tree panel is hidden; FALSE = tree panel is visible
18 boolean TRUE = tree panel has focus; FALSE = editor panel has focus

19 boolean TRUE = Hide checked nodes; FALSE = All nodes are visible (New in 1.7.0) [dpv]


position type meaning
---------- -------------- --------------
1 boolean Check state: TRUE = node is checked; FALSE = node is unchecked
2 boolean Flag state (reserved for internal use; must be 0)
3 boolean Bold state: TRUE = node caption is displayed in bold font; FALSE = node caption is displayed in normal font style
4 boolean (unused - obsolete)
5 boolean (unused - obsolete)
6 integer Virtual node indicator: 0 = not a virtual node;
1 = virtual node with plain text data;
2 = virtual node with RTF data
7 boolean TRUE = node is expanded; FALSE = node is collapsed
8 boolean TRUE = node caption has its own font color; FALSE = node caption color is default
9 boolean TRUE = node caption has its own background color;
FALSE = node caption background color is default
10 integer Word wrap setting for node. Valid values are 0, 1 and 2.
'0' = use the Note's wordwrap setting (for backwards compatibility);
1 = WordWrap ON;
2 = WordWrap OFF
11 boolean TRUE = Show children checkBoxes (New in 1.7.0) [dpv]
FALSE= Hide children checkBoxes
12 boolean TRUE = Node is filtered (hidden) (New in 1.7.0) [dpv]
FALSE= Node is not filtered (visile)


IMPORTANT NOTES about the RTF data section:

1. The data section may be empty or missing entirely, which will not invalidate the file. This allows you to easily create file templates without having to worry about supplying valid RTF data: your template can simply define the structure (notes and nodes), while leaving out the data sections, which users will fill in as they create files based on the template.

2. If the flags string for a note contains '1' at sixth position (see above), the note has been marked as "Plain text only" (Note properties|Advanced). When storing plain text data in the RTF data section, we could encounter lines which would be interpreted by KeyNote as section markers (i.e. if the note has a line that consists only of a percent sign, it would be interpreted as a start of a new note). This cannot happen in RTF data, because there will at least be a trailing backslash or "\par" token, but for plain-text data we MUST avoid the possibility of such conflicts.

Therefore, if the note has been marked as plain-text, KeyNote prepends a semicolon (;) to each data line, like this:

;one line of text in a plain-text note
;another line of text.

These semicolons must be stripped before displaying the text.

Other than this, RTF data is stored without any changes whatsoever.

--- END ---

Imágenes de KeyNote 1.7.1

Las siguientes son algunas imágenes de la nueva versión:


Nueva opción: Children Checkbox

Después de aplicar la opción Children Checkbox y tras marcar dos como finalizados

Ocultando los nodos marcados como finalizados

Dos nuevas opciones de búsqueda:
- Search hidden nodes
- Filter tree note

Una nota filtrada a partir del criterio de búsqueda realizado. Los nodos seleccionados se muestran en azul (también se muestran los padres de éstos para respetar la jerarquía)

Al exportar es posible excluir los nodos ocultos

Nueva opción: Set Alarm...
Permite asociar alarmas a nodos. Se guardan en el propio fichero, actualmente sólo se dispararán si éste se mantiene abierto.

La pantalla que permite establecer, posponer y descartar alarmas

Nuevas funciones:
- Set Alarm...
- Show or Hide checked nodes
- Apply Filter on tree note


Nueva versión de KeyNote: 1.7.1

Muchísima gente conoce y disfruta del programa KeyNote, realizado por Marek Jedlinsk:

Su propia página:

Yo mismo lo uso muchísimo, pues hay que reconocer que es tremendamente útil y funciona muy bien.
Pero por lo mismo que lo uso tanto también le he venido a echar falta cierta funcionalidad. Por ello, a finales del año pasado me animé a descargarme el código fuente (está escrito en Delphi, en su mayoría preparado para Delphi 3, una versión ya algo antigua), a intentar comprenderlo y a modificarlo, corrigiendo algunas cosas y mejorando otras.

Me costó al principio porque lo primero que quise hacer adaptarlo a Delphi 2006; además, no estaban incluidos en el paquete que ofrecía Marek todos los ficheros de los componentes de terceros que se estaban utilizando. Entre otras cosas eso impedía compilar el programa. Al final, buscando por internet localicé esos ficheros (o al menos algunos que parecían equivalentes..) Tras algunas adaptaciones a la versión Delphi 2006 conseguí generar un ejecutable de KeyNote que funcionaba.
Para poder comprender mejor el programa y facilitar los cambios hice también un poco de reestructuración de algunos fuentes, principalmente extraer algunos métodos del fichero Kn_Main.pas (extremadamente grande y con funciones de todo tipo) y colocarlos en otros ficheros (o ya existentes o nuevos, en función de su cometido).

A partir de ahí realicé una serie de correcciones y adaptaciones:

25 November 2007 - version 1.7.1
* Añadida la posibilidad de establecer alarmas, asociadas a nodos

13 November 2007 - version 1.7.0
* Corregido un error que podía afectar tanto a las búsquedas como
a las exportaciones o al envío de email. En algunas raras ocasiones
el contenido de un nodo podía provocar que el mecanismo de búsqueda
se "bloqueara" en ese nodo: el contenido del nodo es volcado sobre
un control auxiliar; para algunos contenidos (muy pocos y raros)
una vez volcados en el control auxiliar éste no podía ser limpiado
ni reemplazado. Se ha adoptado una solución de compromiso: cuando
esto ocurre simplemente se elimina y se vuelve a crear nuevamente el
Lo extraño es que este comportamiento se daba con cualquier control
temporal que se crease (TRxRichEdit, TRichEdit, TTabRichEdit), pero
no si como control auxiliar se usaba ActiveNote.Editor u otro editor
de otras pestañas. No he llegado a encontrar ninguna propiedad establecida
en ActiveNote.Editor que justifique la diferencia de comportamiento.
* Cambiado el comportamiento de ESCAPE en la ventana Scratch. En lugar
de pasar el foco al control de edición de la nota, minimiza KeyNote.
* Se mantiene la posibilidad de seleccionar Checkboxes para todos los nodos
(View/Tree Checkboxes -- Ahora View/All nodes Checkboxes) y se añade la
de poder mostrar Checkboxes sólo en los nodos hijos de uno dado.
(Children Checkbox)

* Corregido el error que hacía que se perdiera la marca de check al mover
un nodo. Ahora se mantiene tanto si se realiza mediante drag and drop
como con Shift, también se respeta si se trasfiere el nodo (o subárbol).
De momento, si se mueve un nodo con Checkbox hacia otro que no muestra
checkboxes para sus hijos tampoco se mostrará en éste (aunque la marca de
check no se habrá perdido)

* Añadida la capacidad de ocultar nodos. Esto puede conseguirse de dos formas
** Activando un modo que oculta automáticamente los nodos chequeados
(Show or Hide checked nodes)
** Filtrando los nodos de una nota o todas las notas en base a los criterios
de búsqueda (Filter Tree Note)

En las búsquedas (y filtrados) es posible indicar si se quiere o no
considerar también los nodos ocultos.
Al seguir un favorito que apunte a un nodo oculto éste se hará visible.
Los nodos ocultos (por estar chequeados y aplicado el botón Check Hidden Nodes
o bien por haber sido filtrados) no impiden realizar cualquiera de las funciones
que se pueden aplicar a un árbol.

Con esto ya realizado me intenté poner en contacto con el autor, entre otras cosas para comunicarle los nuevos cambios hechos y solicitarle consejo sobre cómo dar a conocer esta nueva versión. Yo sólo he hecho algunas pequeñas mejoras, TODO el trabajo y el mérito evidentemente lo tiene él.
Ahora bien, pensé que también debía yo aparecer en el 'About KeyNote', pero dejando muy claro qué es lo que yo había hecho.

Hoy he comprobado que el proyecto dentro de está teniendo vida en su foro. Hay muchas personas que se siguen interesando por el programa y que se plantean evolucionarlo. Por ello me he animado a escribir un post en ese foro:
explicando (en mi mal inglés) básicamente lo que aquí digo.

En principio mi idea no es continuar evolucionando este programa. Estoy trabajando en un nuevo programa con otra filosofía de diseño, y desarrollado en .NET. Al igual que Marek yo también lo haré disponible mediante alguna licencia de software libre. Cuando tenga consistencia lo iré dando a conocer.

De todas formas me parece una pena que no se aproveche el trabajo que ya he hecho, entre otras cosas porque estoy convencido de que hay muchísima gente que sigue utilizando KeyNote y le pueden resultar útiles las mejoras que le añadido (también algunas correcciones)

Por ello, aunque no sé muy bien dónde debería colgar tanto los fuentes como el nuevo ejecutable, lo haré si hay gente que está interesada. Aprovecho para pedir sugerencias sobre cómo hacerlo, pues no tengo experiencia en la publicación de software libre y quiero, tanto respetar adecuadamente la autoría de Marek como que se garantice el trabajo hecho por mí.

Nota: no he preparado todavía (ni tengo por ahora previsto hacerlo) ningún nuevo programa de instalación. Por ello, lo que hay que hacer es instalar la versión última de KeyNote (1.6.5) --si es que aún no se ha hecho-- y reemplazar el ejecutable Keynote.exe. También se debería sustituir la ayuda Keynote.hlp por un nuevo KeyNote.chm, así como sería correcto reemplazar los ficheros readme.txt y History.txt.

Para implementar algunos de los cambios de la nueva versión he tenido que ampliar ligeramente la especificación del formato de un fichero KeyNote. Todos los nuevos elementos son opcionales, por lo que la nueva versión puede abrir sin problemas un fichero correspondiente a la versión 1.6.5