[liblouis-liblouisxml] [liblouisutdml] push by mwhapples - Changes by Paul Wood on 2014-09-22 08:48 GMT

  • From: liblouisutdml@xxxxxxxxxxxxxx
  • To: liblouis-liblouisxml@xxxxxxxxxxxxx
  • Date: Mon, 22 Sep 2014 08:49:10 +0000

Revision: 5dcd8a94c8ca
Branch:   default
Author:   Paul Wood <paulw@xxxxxxxxxxxxxx>
Date:     Fri Sep 19 15:51:24 2014 UTC
Log:      Changes by Paul Wood
https://code.google.com/p/liblouisutdml/source/detail?r=5dcd8a94c8ca

Added:
 /liblouisutdml/makeEndnotes.c
 /tests/test_suite/test_14/Makefile.am
 /tests/test_suite/test_14/README
 /tests/test_suite/test_14/expected.txt
 /tests/test_suite/test_14/identity.cti
 /tests/test_suite/test_14/input.xml
 /tests/test_suite/test_14/liblouisutdml.ini
 /tests/test_suite/test_14/nabcc.dis
 /tests/test_suite/test_14/pagenum.cti
 /tests/test_suite/test_14/semantics.sem
 /tests/test_suite/test_14/styles.cfg
 /tests/test_suite/test_14/whitespace.cti
 /tests/test_suite/test_14/xfail
Modified:
 /liblouisutdml/Makefile.am
 /liblouisutdml/louisutdml.h
 /liblouisutdml/readconfig.c
 /liblouisutdml/sem_enum.h
 /liblouisutdml/sem_names.h
 /liblouisutdml/transcribe_paragraph.c
 /liblouisutdml/transcriber.c
 /tests/test_suite/Makefile.am

=======================================
--- /dev/null
+++ /liblouisutdml/makeEndnotes.c       Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,596 @@
+/* liblouisutdml Braille Transcription Library
+
+   This file may contain code borrowed from the Linux screenreader
+   BRLTTY, copyright (C) 1999-2006 by
+   the BRLTTY Team
+
+   Copyright (C) 2004, 2005, 2006
+   ViewPlus Technologies, Inc. www.viewplus.com
+   and
+   Abilitiessoft, Inc. www.abilitiessoft.com
+   All rights reserved
+
+   This file is free software; you can redistribute it and/or modify it
+   under the terms of the Lesser or Library GNU General Public License
+   as published by the
+   Free Software Foundation; either version 3, or (at your option) any
+   later version.
+
+   This file is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   Library GNU General Public License for more details.
+
+   You should have received a copy of the Library GNU General Public
+   License along with this program; see the file COPYING.  If not, write to
+   the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+
+   Maintained by John J. Boyer john.boyer@xxxxxxxxxxxxxxxxx
+   */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "louisutdml.h"
+
+typedef struct EndnoteStruct EndnoteStruct;
+typedef enum free_codes free_codes;
+
+struct EndnoteStruct
+ {
+   EndnoteStruct* next;
+   EndnoteStruct* prev;
+   char* id;
+   int id_length;
+   widechar* character;
+   int character_length;
+   widechar* page_num;
+   int page_num_length;
+   widechar* line_num;
+   int line_num_length;
+   widechar* endnote;
+   int endnote_length;
+   int has_endnote_pos;
+   int free_code;
+ };
+
+static EndnoteStruct workingEndnote;
+static EndnoteStruct *firstEndnote;
+static EndnoteStruct *lastEndnote;
+static widechar* notes_header;
+static int notes_header_length;
+static widechar* notes_description;
+static int notes_description_length;
+static int old_translated_length;
+
+static void free_endnotes_from(EndnoteStruct *start);
+
+//initialisation to make sure everything is set up correctly
+int initialize_endnotes (void)
+{
+  static int initialized=0;
+  if(!initialized)
+  {
+       firstEndnote = NULL;
+       lastEndnote = NULL;
+       notes_header = NULL;
+       notes_description = NULL;
+       notes_header_length = 0;
+       notes_description_length = 0;
+       ud->endnote_stage=1;
+       initialized=1;
+  }
+  return 1;
+}
+
+// finds the endnote with id 'id' and returns a pointer to that endnote.
+static EndnoteStruct* find_endnote_from_id(const char* id)
+{
+       EndnoteStruct* current;
+
+       for(current = firstEndnote;current!=NULL;current=current->next)
+       {
+               if(strcmp(current->id,id)==0)
+                       return current;
+       }
+       return NULL;
+}
+
+// returns the length of the current braille page number string
+static int braille_page_num_length()
+{
+       int braille_string_length=0;
+       while(ud->braille_page_string[braille_string_length])
+               braille_string_length++;
+       return braille_string_length;
+}
+
+// roughly copied from hyphenatex in transcriber.c, taking out any code that
+// isn't needed in this situation and made changes as below:
+// instead of lastBlank, this takes in wordStart, which should be lastBlank+1.
+// added wordLength argument, as already calculated where needed.
+// no need for hyphenAdded so removed.
+// breakAt returns the relative position from wordStart (breakAt=k), rather than
+// the absolute position (breakAt=wordStart+k).
+static int hyphenatex (int wordStart, int wordLength,int lineEnd, int *breakAt)
+{
+#define MIN_SYLLABLE_LENGTH 2
+#define MIN_WORD_LENGTH 5
+#define MIN_NEXT_LINE 12
+#define minimum(a,b) ((a<b)?a:b)
+
+  int k;
+  char hyphens[MAXNAMELEN];
+
+  if (ud->hyphenate != 1 && ud->hyphenate != 2)
+    return 0;
+
+  if ((ud->translated_length - wordStart) < MIN_NEXT_LINE)
+    return 0;
+
+  if (wordLength < MIN_WORD_LENGTH || wordLength > ud->cells_per_line)
+    return 0;
+
+  for (k = minimum(lineEnd - wordStart, wordLength - MIN_SYLLABLE_LENGTH);
+       k > MIN_SYLLABLE_LENGTH;
+       k--)
+    {
+         if(ud->translated_buffer[wordStart + k - 1] == *ud->lit_hyphen)
+           {
+             *breakAt = k;
+             return 1;
+           }
+    }
+
+  for (k = 0; k <= wordLength; k++)
+    hyphens[k] = '0';
+
+  if (!lou_hyphenate (ud->main_braille_table,
+                          &ud->translated_buffer[wordStart], wordLength,
+                          hyphens, 1))
+    return 0;
+
+ for (k = minimum(lineEnd - wordStart, wordLength - MIN_SYLLABLE_LENGTH) - 1;
+       k > MIN_SYLLABLE_LENGTH;
+       k--)
+    if (hyphens[k] == '1')
+      {
+       *breakAt = k;
+       return 1;
+      }
+
+  return 0;
+}
+
+// starting at the current line (the line of the start of the current paragraph), +// this returns the line number and page number (in 'pagenum' and 'linenum' respectively),
+// from the number of characters that need to be written ('num_chars').
+// could be improved/replaced as most likely not perfect.
+static void get_page_line_num(int num_chars,int* pagenum,int* linenum)
+{
+       int first_line = 1;
+       int line_num = ud->lines_on_page+ud->blank_lines+1;
+       int page_num = ud->braille_page_number;
+       int chars_done = 0;
+       int available_cells = ud->cells_per_line;
+       available_cells -= ud->style_first_line_indent;
+       if(line_num==1)
+               available_cells -= braille_page_num_length();
+       available_cells -= ud->style_left_margin;
+       available_cells -= ud->style_right_margin;
+       while(chars_done < num_chars)
+       {
+               int word_length;
+
+               if(num_chars - chars_done < available_cells)
+                       break;
+               else
+               {
+                       int last_word_begin;
+                       int breakat;
+
+                       
for(last_word_begin=available_cells;last_word_begin>0;last_word_begin--)
+                               
if(ud->translated_buffer[chars_done+last_word_begin] == ' ')
+                                       break;
+
+ for(word_length = last_word_begin+1;chars_done+word_length<num_chars;word_length++)
+                               
if(ud->translated_buffer[chars_done+word_length] == ' ')
+                                       break;
+                       word_length-=last_word_begin;
+
+                       line_num++;
+                       available_cells = ud->cells_per_line;
+                       available_cells -= ud->style_left_margin;
+                       available_cells -= ud->style_right_margin;
+                       if(last_word_begin==0)
+                               available_cells -= (word_length+1);
+                       else if(ud->hyphenate)
+                       {
+ if(hyphenatex(chars_done+last_word_begin+1,word_length,chars_done+available_cells,&breakat))
+                                       available_cells -= 
(word_length-breakat+1);
+                               else
+                                       available_cells -= (word_length+1);
+                       }
+                       else
+                               available_cells -= (word_length+1);
+
+                       chars_done += last_word_begin+word_length + 1;
+                       if(line_num > ud->lines_per_page)
+                       {
+                               if(ud->style_format == centered)
+                                       available_cells -= 
2*braille_page_num_length();
+                               else
+                                       available_cells -= 
braille_page_num_length();
+                               page_num++;
+                               line_num=1;
+                       }
+               }
+       }
+       *linenum = line_num;
+       *pagenum = page_num;
+}
+
+// gets the current translation length for use in finish_endnote
+ int start_endnote(void)
+ {
+       insert_translation(ud->main_braille_table);
+       old_translated_length = ud->translated_length;
+       return 1;
+ }
+
+// uses the change in length of the translation buffer to
+// calculate the content of 'node', which it uses for the endnote
+// character, and the attribute of 'node' as its id.
+int finish_endnote(xmlNode* node)
+{
+       xmlNode *child;
+       int node_translated_length;
+       int k;
+       int branchCount=0;
+       EndnoteStruct* endnotePtr;
+       char buffer[MAXNUMLEN];
+       int found_endnote=0;
+       int lines_added;
+       int line_num;
+       int page_num;
+
+       endnotePtr = find_endnote_from_id(get_attr_value(node));
+       if(endnotePtr == NULL)
+       {
+               endnotePtr = &workingEndnote;
+               endnotePtr->id = get_attr_value(node);
+               endnotePtr->id_length = strlen(endnotePtr->id);
+       }
+       else if(endnotePtr != NULL && endnotePtr->has_endnote_pos!=0)
+       {
+ logMessage(LOG_DEBUG,"finish_endnote:Endnote with id %s already exists",get_attr_value(node));
+               return 0;
+       }
+       else found_endnote=1;
+
+       insert_translation (ud->main_braille_table);
+
+       node_translated_length = ud->translated_length - old_translated_length;
+
+       if(node_translated_length == 0) return 0;               // no endnote 
character
+
+       if(ud->translated_buffer[ud->translated_length-1]==32)
+               ud->translated_length--;
+
+       endnotePtr->character_length = node_translated_length;
+       endnotePtr->character = malloc(endnotePtr->character_length * CHARSIZE);
+ memcpy(endnotePtr->character,&ud->translated_buffer[old_translated_length],endnotePtr->character_length*CHARSIZE);
+       if(ud->translated_buffer[old_translated_length-1]==32)
+       {
+ memmove(&ud->translated_buffer[old_translated_length+2],&ud->translated_buffer[old_translated_length],endnotePtr->character_length*CHARSIZE);
+               ud->translated_length+=2;
+ ud->translated_buffer[old_translated_length]=ud->translated_buffer[old_translated_length+1]='9';
+       }
+       else if(ud->translated_buffer[old_translated_length]==32)
+       {
+ memmove(&ud->translated_buffer[old_translated_length+3],&ud->translated_buffer[old_translated_length+1],(endnotePtr->character_length-1)*CHARSIZE); + ud->translated_buffer[old_translated_length+1]=ud->translated_buffer[old_translated_length+2]='9';
+               ud->translated_length+=2;
+       }
+       if(!(endnotePtr->free_code & 1)) endnotePtr->free_code += 1;
+
+       get_page_line_num(ud->translated_length,&page_num,&line_num);
+
+       itoa(line_num,buffer,10);
+       for(k=0;k<strlen(buffer);k++)
+               ud->text_buffer[k]=buffer[k];
+       ud->text_length = strlen(buffer);
+       old_translated_length = ud->translated_length;
+       insert_translation(ud->main_braille_table);
+       if(ud->translated_buffer[old_translated_length]==32)
+       {
+ endnotePtr->line_num_length = ud->translated_length-old_translated_length-1;
+               endnotePtr->line_num = malloc(endnotePtr->line_num_length * 
CHARSIZE);
+ memcpy(endnotePtr->line_num,&ud->translated_buffer[old_translated_length+1],endnotePtr->line_num_length*CHARSIZE);
+       }
+       else if(ud->translated_buffer[old_translated_length-1]==32)
+       {
+ endnotePtr->line_num_length = ud->translated_length-old_translated_length;
+               endnotePtr->line_num = malloc(endnotePtr->line_num_length * 
CHARSIZE);
+ memcpy(endnotePtr->line_num,&ud->translated_buffer[old_translated_length],endnotePtr->line_num_length*CHARSIZE);
+       }
+       ud->translated_length = old_translated_length;
+       if(!(endnotePtr->free_code & 8)) endnotePtr->free_code += 8;
+
+
+       itoa(page_num,buffer,10);
+       for(k=0;k<strlen(buffer);k++)
+               ud->text_buffer[k]=buffer[k];
+       ud->text_length = strlen(buffer);
+       old_translated_length = ud->translated_length;
+       insert_translation(ud->main_braille_table);
+       if(ud->translated_buffer[old_translated_length]==32)
+       {
+ endnotePtr->page_num_length = ud->translated_length-old_translated_length-1;
+               endnotePtr->page_num = 
malloc(endnotePtr->line_num_length*CHARSIZE);
+ memcpy(endnotePtr->page_num,&ud->translated_buffer[old_translated_length+1],endnotePtr->page_num_length*CHARSIZE);
+       }
+       else if(ud->translated_buffer[old_translated_length-1]==32)
+       {
+ endnotePtr->page_num_length = ud->translated_length-old_translated_length;
+               endnotePtr->line_num = malloc(endnotePtr->page_num_length * 
CHARSIZE);
+ memcpy(endnotePtr->line_num,&ud->translated_buffer[old_translated_length],endnotePtr->page_num_length*CHARSIZE);
+       }
+       ud->translated_length = old_translated_length;
+       if(!(endnotePtr->free_code & 4)) endnotePtr->free_code += 4;
+
+       if(found_endnote)
+       {
+               if(endnotePtr != lastEndnote)
+               {
+                       if(endnotePtr == firstEndnote)
+                       {
+                               firstEndnote = endnotePtr->next;
+                               (endnotePtr->next)->prev = NULL;
+                               endnotePtr->prev = lastEndnote;
+                               endnotePtr->next = NULL;
+                               lastEndnote->next = endnotePtr;
+                               lastEndnote = endnotePtr;
+                       }
+                       else
+                       {
+                               (endnotePtr->prev)->next = endnotePtr->next;
+                               (endnotePtr->next)->prev = endnotePtr->prev;
+                               endnotePtr->prev = lastEndnote;
+                               endnotePtr->next = NULL;
+                               lastEndnote->next = endnotePtr;
+                               lastEndnote = endnotePtr;
+                       }
+               }
+               endnotePtr->has_endnote_pos=1;
+               return 1;
+       }
+
+       endnotePtr->has_endnote_pos=1;
+       endnotePtr->next = NULL;
+       endnotePtr->prev = lastEndnote;
+       endnotePtr = malloc (sizeof(workingEndnote));
+       memcpy (endnotePtr, &workingEndnote, sizeof(workingEndnote));
+       if (lastEndnote != NULL)
+               lastEndnote->next = endnotePtr;
+       lastEndnote = endnotePtr;
+       if (firstEndnote == NULL)
+               firstEndnote = endnotePtr;
+}
+
+// called when a note cannot find a noteref with the same id.
+// assumes that the noteref will come after it.
+// creates a basic endnote that contains the endnote description and id from 'node'.
+// when create_endnote is called (from a noteref), it checks all the
+// endnotes created by this function, and if it finds one with the same id,
+// adds the rest of the information.
+int create_endnote_shell(xmlNode* node)
+{
+       int k;
+       EndnoteStruct* endnotePtr;
+
+       workingEndnote.id = get_attr_value(node);
+       workingEndnote.id_length = strlen(workingEndnote.id);
+
+       workingEndnote.free_code = 0;
+
+       workingEndnote.endnote_length=ud->translated_length;
+       workingEndnote.endnote = malloc(workingEndnote.endnote_length*CHARSIZE);
+       for(k=0;k<workingEndnote.endnote_length;k++)
+               workingEndnote.endnote[k] = ud->translated_buffer[k];
+       if(!(workingEndnote.free_code & 2))
+               workingEndnote.free_code += 2;
+
+       workingEndnote.has_endnote_pos=0;
+       workingEndnote.next = NULL;
+       workingEndnote.prev = lastEndnote;
+       endnotePtr = malloc (sizeof(workingEndnote));
+       memcpy (endnotePtr, &workingEndnote, sizeof(workingEndnote));
+       if (lastEndnote != NULL)
+               lastEndnote->next = endnotePtr;
+       lastEndnote = endnotePtr;
+       if (firstEndnote == NULL)
+               firstEndnote = endnotePtr;
+}
+
+// called by the note action.
+// tries to find a corresponding noteref with the id from the attribute of 'node'. +// if it finds it, then it adds the content of 'node' as the description of this endnote. +// if it doesn't find it, then it creates a new basic endnote (see create_endnote_shell), +// containing just the id and description, hoping to link up to a noteref later on. +// note: when the endnotes are being displayed, any endnotes that are created as basic ones +// from here, but do not link up to a noteref later on, will not be displayed.
+int link_endnote(xmlNode* node)
+{
+       EndnoteStruct* linked = find_endnote_from_id(get_attr_value(node));
+
+       if(linked==NULL)
+               create_endnote_shell(node);
+       else if(linked!=NULL && linked->has_endnote_pos==1)
+       {
+               int k;
+               linked->endnote_length=ud->translated_length;
+               linked->endnote = malloc(linked->endnote_length * CHARSIZE);
+
+               for(k=0;k<linked->endnote_length;k++)
+                       linked->endnote[k] = ud->translated_buffer[k];
+
+               if(!(linked->free_code & 2)) linked->free_code += 2;
+       }
+       else
+       {
+ logMessage(LOG_DEBUG,"link_endnote:Endnote with id %s already exists",get_attr_value(node));
+               return 0;
+       }
+
+       return 1;
+}
+
+// set the notes header as what has been translated.
+// if one is already set, then this overwrites it.
+void set_notes_header()
+{
+       if(notes_header==NULL)
+       {
+               notes_header = malloc(ud->translated_length * CHARSIZE);
+ memcpy(notes_header,ud->translated_buffer,ud->translated_length*CHARSIZE);
+               notes_header_length = ud->translated_length;
+       }
+       else
+       {
+               free(notes_header);
+               notes_header=NULL;
+               set_notes_header();
+       }
+}
+
+// set the notes description as what has been translated.
+// if one is already set, then this overwrites it.
+void set_notes_description()
+{
+       if(notes_description==NULL)
+       {
+               notes_description = malloc(ud->translated_length * CHARSIZE);
+ memcpy(notes_description,ud->translated_buffer,ud->translated_length*CHARSIZE);
+               notes_description_length = ud->translated_length;
+       }
+       else
+       {
+               free(notes_description);
+               notes_description=NULL;
+               set_notes_description();
+       }
+}
+
+// called at the end of the translating process.
+// this adds the endnote header and description using their respective styles, +// then steps through all the endnotes in order, adding in the endnote character,
+// its page and line number, and its note.
+int make_endnotes(void)
+{
+       EndnoteStruct* current_endnote = NULL;
+
+       ud->endnote_stage = 2;
+       if(!ud->endnotes) return 1;
+
+       if(firstEndnote != NULL)
+       {
+               int k;
+               StyleType* style;
+               int has_newline=0;
+               do_newpage();
+               if(ud->running_head_length>0)
+               {
+                       do_blankline();
+                       has_newline=1;
+               }
+               insert_translation(ud->main_braille_table);
+               if(notes_header_length > 0)
+               {
+                       style = action_to_style(notesheader);
+                       start_style(style,NULL);
+ memcpy(&ud->translated_buffer[ud->translated_length],notes_header,notes_header_length*CHARSIZE);
+                       ud->translated_length+=notes_header_length;
+                       end_style(style);
+                       do_blankline();
+                       has_newline=1;
+                       free(notes_header);
+               }
+               if(notes_description_length)
+               {
+                       style = action_to_style(notesdescription);
+                       start_style(style,NULL);
+ memcpy(&ud->translated_buffer[ud->translated_length],notes_description,notes_description_length*CHARSIZE);
+                       ud->translated_length+=notes_description_length;
+                       end_style(style);
+                       do_blankline();
+                       has_newline=1;
+                       free(notes_description);
+               }
+               if(!has_newline)
+                       do_blankline();
+               current_endnote = firstEndnote;
+               while (current_endnote != NULL)
+               {
+                       if(!current_endnote->has_endnote_pos)
+                       {
+                               current_endnote = current_endnote->next;
+                               continue;
+                       }
+                       style = action_to_style(note);
+                       start_style(style,NULL);
+ memcpy(&ud->translated_buffer[ud->translated_length],current_endnote->character,current_endnote->character_length*CHARSIZE);
+                       ud->translated_length += 
current_endnote->character_length;
+                       if(ud->braille_pages && 
current_endnote->page_num_length!=0)
+                       {
+                               ud->translated_buffer[ud->translated_length++] 
= 160;
+                               ud->translated_buffer[ud->translated_length++] 
= 'p';
+ memcpy(&ud->translated_buffer[ud->translated_length],current_endnote->page_num,current_endnote->page_num_length*CHARSIZE);
+                               if(current_endnote->line_num_length!=0)
+                               {
+                                       ud->translated_length += 
current_endnote->page_num_length;
+ memcpy(&ud->translated_buffer[ud->translated_length],current_endnote->line_num,current_endnote->line_num_length*CHARSIZE);
+                                       ud->translated_length += 
current_endnote->line_num_length;
+                               }
+                       }
+                       ud->translated_buffer[ud->translated_length++] = ' ';
+ memcpy(&ud->translated_buffer[ud->translated_length],current_endnote->endnote,current_endnote->endnote_length*CHARSIZE);
+                       ud->translated_length += 
current_endnote->endnote_length;
+                       end_style(style);
+                       ud->in_sync=0;
+                       current_endnote = current_endnote->next;
+               }
+               do_newpage ();
+               write_buffer(1,0);
+               free_endnotes_from (firstEndnote);
+               firstEndnote = NULL;
+    }
+  return 1;
+}
+
+// frees the memory of all resources belonging to 'endnote'
+static void free_endnote(EndnoteStruct* endnote)
+{
+       if(endnote->free_code&1) free(endnote->character);
+       if(endnote->free_code&2) free(endnote->endnote);
+       if(endnote->free_code&4) free(endnote->page_num);
+       if(endnote->free_code&8) free(endnote->line_num);
+       free(endnote);
+}
+
+// frees the memory of all the endnotes that appear after 'start'
+static void free_endnotes_from(EndnoteStruct *start)
+ {
+   EndnoteStruct *current;
+   EndnoteStruct *next;
+   if (start == NULL) return;
+   current = start;
+   while (current != NULL)
+       {
+               next = current->next;
+               free_endnote(current);
+               current = next;
+       }
+ }
+
=======================================
--- /dev/null
+++ /tests/test_suite/test_14/Makefile.am       Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,13 @@
+EXTRA_DIST =                                   \
+       expected.txt                            \
+       identity.cti                            \
+       input.xml                               \
+       liblouisutdml.ini                       \
+       nabcc.dis                               \
+       output.txt                              \
+       pagenum.cti                             \
+       README                                  \
+       semantics.sem                           \
+       styles.cfg                              \
+       whitespace.cti                          \
+       xfail
=======================================
--- /dev/null
+++ /tests/test_suite/test_14/README    Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,1 @@
+Testing printPageNumberRange when a page break in print happens right before a page break in braille (fails when printPageNumberAt=bottom)
=======================================
--- /dev/null
+++ /tests/test_suite/test_14/expected.txt      Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,40 @@
+Foo 99#a Bar.
+Foo 99ref#b Bar.
+
+
+
+
+
+
+
+
+Foo 99#c Bar.
+
+
+
+
+
+
+
+
+
+        Endnotes
+
+Some descriptive text
+
+    #a p#a#a Endnote
+  Description #a
+    ref#b p#a#b Endnote
+  Description #b
+
+
+    #c p#b#a Endnote
+  Description #c
+
+
+
+
+
+
+
+
=======================================
--- /dev/null
+++ /tests/test_suite/test_14/identity.cti      Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,258 @@
+sign \x0020 0
+sign \x0061 1
+sign \x0031 2
+sign \x0062 12
+sign \x0027 3
+sign \x006B 13
+sign \x0032 23
+sign \x006C 123
+sign \x0060 4
+sign \x0063 14
+sign \x0069 24
+sign \x0066 124
+sign \x002F 34
+sign \x006D 134
+sign \x0073 234
+sign \x0070 1234
+sign \x0022 5
+sign \x0065 15
+sign \x0033 25
+sign \x0068 125
+sign \x0039 35
+sign \x006F 135
+sign \x0036 235
+sign \x0072 1235
+sign \x007E 45
+sign \x0064 145
+sign \x006A 245
+sign \x0067 1245
+sign \x003E 345
+sign \x006E 1345
+sign \x0074 2345
+sign \x0071 12345
+sign \x002C 6
+sign \x002A 16
+sign \x0035 26
+sign \x003C 126
+sign \x002D 36
+sign \x0075 136
+sign \x0038 236
+sign \x0076 1236
+sign \x002E 46
+sign \x0025 146
+sign \x007B 246
+sign \x0024 1246
+sign \x002B 346
+sign \x0078 1346
+sign \x0021 2346
+sign \x0026 12346
+sign \x003B 56
+sign \x003A 156
+sign \x0034 256
+sign \x007C 1256
+sign \x0030 356
+sign \x007A 1356
+sign \x0037 2356
+sign \x0028 12356
+sign \x005F 456
+sign \x003F 1456
+sign \x0077 2456
+sign \x007D 12456
+sign \x0023 3456
+sign \x0079 13456
+sign \x0029 23456
+sign \x003D 123456
+sign \x00BA 7
+sign \x0041 17
+sign \x00B9 27
+sign \x0042 127
+sign \x00B4 37
+sign \x004B 137
+sign \x00B2 237
+sign \x004C 1237
+sign \x0040 47
+sign \x0043 147
+sign \x0049 247
+sign \x0046 1247
+sign \x00F7 347
+sign \x004D 1347
+sign \x0053 2347
+sign \x0050 12347
+sign \x00A8 57
+sign \x0045 157
+sign \x00B3 257
+sign \x0048 1257
+sign \x00A7 357
+sign \x004F 1357
+sign \x00B6 2357
+sign \x0052 12357
+sign \x005E 457
+sign \x0044 1457
+sign \x004A 2457
+sign \x0047 12457
+sign \x00BB 3457
+sign \x004E 13457
+sign \x0054 23457
+sign \x0051 123457
+sign \x00B8 67
+sign \x00D7 167
+sign \x00AF 267
+sign \x00AB 1267
+sign \x00AD 367
+sign \x0055 1367
+sign \x00AE 2367
+sign \x0056 12367
+sign \x00B7 467
+sign \x00A4 1467
+sign \x005B 2467
+sign \x00A2 12467
+sign \x00B1 3467
+sign \x0058 13467
+sign \x00A1 23467
+sign \x00A5 123467
+sign \x00B5 567
+sign \x00A6 1567
+sign \x00AC 2567
+sign \x005C 12567
+sign \x00B0 3567
+sign \x005A 13567
+sign \x00A9 23567
+sign \x00BC 123567
+sign \x007F 4567
+sign \x00BF 14567
+sign \x0057 24567
+sign \x005D 124567
+sign \x00A3 34567
+sign \x0059 134567
+sign \x00BE 234567
+sign \x00BD 1234567
+sign \x00AA 8
+sign \x0081 18
+sign \x00E2 28
+sign \x0082 128
+sign \x00E6 38
+sign \x008B 138
+sign \x00EA 238
+sign \x008C 1238
+sign \x0080 48
+sign \x0083 148
+sign \x0089 248
+sign \x0086 1248
+sign \x00F8 348
+sign \x008D 1348
+sign \x0093 2348
+sign \x0090 12348
+sign \x00E3 58
+sign \x0085 158
+sign \x00EE 258
+sign \x0088 1258
+sign \x00F2 358
+sign \x008F 1358
+sign \x00E0 2358
+sign \x0092 12358
+sign \x009E 458
+sign \x0084 1458
+sign \x008A 2458
+sign \x0087 12458
+sign \x00E5 3458
+sign \x008E 13458
+sign \x0094 23458
+sign \x0091 123458
+sign \x00F0 68
+sign \x00E1 168
+sign \x00FB 268
+sign \x00E9 1268
+sign \x00FE 368
+sign \x0095 1368
+sign \x00EC 2368
+sign \x0096 12368
+sign \x00F1 468
+sign \x00ED 1468
+sign \x009B 2468
+sign \x00FD 12468
+sign \x00E7 3468
+sign \x0098 13468
+sign \x00F6 23468
+sign \x00E4 123468
+sign \x00F5 568
+sign \x00FA 1568
+sign \x00F4 2568
+sign \x009C 12568
+sign \x00F9 3568
+sign \x009A 13568
+sign \x00E8 23568
+sign \x00EF 123568
+sign \x009F 4568
+sign \x00F3 14568
+sign \x0097 24568
+sign \x009D 124568
+sign \x00FF 34568
+sign \x0099 134568
+sign \x00FC 234568
+sign \x00EB 1234568
+sign \x00A0 78
+sign \x0001 178
+sign \x00C2 278
+sign \x0002 1278
+sign \x00C6 378
+sign \x000B 1378
+sign \x00CA 2378
+sign \x000C 12378
+sign \x0000 478
+sign \x0003 1478
+sign \x0009 2478
+sign \x0006 12478
+sign \x00D8 3478
+sign \x000D 13478
+sign \x0013 23478
+sign \x0010 123478
+sign \x00C3 578
+sign \x0005 1578
+sign \x00CE 2578
+sign \x0008 12578
+sign \x00D2 3578
+sign \x000F 13578
+sign \x00C0 23578
+sign \x0012 123578
+sign \x001E 4578
+sign \x0004 14578
+sign \x000A 24578
+sign \x0007 124578
+sign \x00C5 34578
+sign \x000E 134578
+sign \x0014 234578
+sign \x0011 1234578
+sign \x00D0 678
+sign \x00C1 1678
+sign \x00DB 2678
+sign \x00C9 12678
+sign \x00DE 3678
+sign \x0015 13678
+sign \x00CC 23678
+sign \x0016 123678
+sign \x00D1 4678
+sign \x00CD 14678
+sign \x001B 24678
+sign \x00DD 124678
+sign \x00C7 34678
+sign \x0018 134678
+sign \x00D6 234678
+sign \x00C4 1234678
+sign \x00D5 5678
+sign \x00DA 15678
+sign \x00D4 25678
+sign \x001C 125678
+sign \x00D9 35678
+sign \x001A 135678
+sign \x00C8 235678
+sign \x00CF 1235678
+sign \x001F 45678
+sign \x00D3 145678
+sign \x0017 245678
+sign \x001D 1245678
+sign \x00DF 345678
+sign \x0019 1345678
+sign \x00DC 2345678
+sign \x00CB 12345678
+
+
=======================================
--- /dev/null
+++ /tests/test_suite/test_14/input.xml Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<doc>
+               <notesheader>not seen header</notesheader>
+               <notesdescription>not seen description</notesdescription>
+
+               <note id = "3">Endnote Description 3</note>
+
+               <p>Foo<noteref id = "1">1</noteref>Bar.</p>
+               <p>Foo<noteref id = "2">ref2</noteref>Bar.</p>
+               <newpage/>
+               <p>Foo<noteref id = "3">3</noteref>Bar.</p>
+
+               <notesheader>Endnotes</notesheader>
+               <notesdescription>Some descriptive text</notesdescription>
+
+               <note id = "1">Endnote Description 1</note>
+               <note id = "2">Endnote Description 2</note>
+</doc>
=======================================
--- /dev/null
+++ /tests/test_suite/test_14/liblouisutdml.ini Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,36 @@
+cellsPerLine 25
+linesPerPage 8
+interpoint no
+lineEnd \n
+pageEnd \f\n
+fileEnd ^z
+printPages no
+braillePages yes
+pageSeparator no
+pageSeparatorNumber no
+numberBraillePages yes
+paragraphs yes
+beginningPageNumber 1
+printPageNumberAt bottom
+printPageNumberRange yes
+braillePageNumberAt top
+mergeUnnumberedPages no
+printPageNumbersInContents yes
+braillePageNumbersInContents yes
+hyphenate pre
+outputEncoding UTF8
+inputTextEncoding UTF8
+backFormat plain
+backLineLength 70
+formatFor textDevice
+lineFill '
+semanticFiles semantics.sem
+literaryTextTable nabcc.dis,whitespace.cti,identity.cti,pagenum.cti
+editTable nabcc.dis,whitespace.cti,identity.cti,pagenum.cti
+xmlheader "<?xml version='1.0' encoding='UTF8' standalone='yes'?>"
+internetAccess no
+newEntries no
+endnotes yes
+
+style document
+style para
=======================================
--- /dev/null
+++ /tests/test_suite/test_14/nabcc.dis Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,262 @@
+# This file will produce 8 dot NABCC output.
+
+display \x0020 a
+
+display \x0020 0
+display \x0061 1
+display \x0031 2
+display \x0062 12
+display \x0027 3
+display \x006B 13
+display \x0032 23
+display \x006C 123
+display \x0060 4
+display \x0063 14
+display \x0069 24
+display \x0066 124
+display \x002F 34
+display \x006D 134
+display \x0073 234
+display \x0070 1234
+display \x0022 5
+display \x0065 15
+display \x0033 25
+display \x0068 125
+display \x0039 35
+display \x006F 135
+display \x0036 235
+display \x0072 1235
+display \x007E 45
+display \x0064 145
+display \x006A 245
+display \x0067 1245
+display \x003E 345
+display \x006E 1345
+display \x0074 2345
+display \x0071 12345
+display \x002C 6
+display \x002A 16
+display \x0035 26
+display \x003C 126
+display \x002D 36
+display \x0075 136
+display \x0038 236
+display \x0076 1236
+display \x002E 46
+display \x0025 146
+display \x007B 246
+display \x0024 1246
+display \x002B 346
+display \x0078 1346
+display \x0021 2346
+display \x0026 12346
+display \x003B 56
+display \x003A 156
+display \x0034 256
+display \x007C 1256
+display \x0030 356
+display \x007A 1356
+display \x0037 2356
+display \x0028 12356
+display \x005F 456
+display \x003F 1456
+display \x0077 2456
+display \x007D 12456
+display \x0023 3456
+display \x0079 13456
+display \x0029 23456
+display \x003D 123456
+display \x00BA 7
+display \x0041 17
+display \x00B9 27
+display \x0042 127
+display \x00B4 37
+display \x004B 137
+display \x00B2 237
+display \x004C 1237
+display \x0040 47
+display \x0043 147
+display \x0049 247
+display \x0046 1247
+display \x00F7 347
+display \x004D 1347
+display \x0053 2347
+display \x0050 12347
+display \x00A8 57
+display \x0045 157
+display \x00B3 257
+display \x0048 1257
+display \x00A7 357
+display \x004F 1357
+display \x00B6 2357
+display \x0052 12357
+display \x005E 457
+display \x0044 1457
+display \x004A 2457
+display \x0047 12457
+display \x00BB 3457
+display \x004E 13457
+display \x0054 23457
+display \x0051 123457
+display \x00B8 67
+display \x00D7 167
+display \x00AF 267
+display \x00AB 1267
+display \x00AD 367
+display \x0055 1367
+display \x00AE 2367
+display \x0056 12367
+display \x00B7 467
+display \x00A4 1467
+display \x005B 2467
+display \x00A2 12467
+display \x00B1 3467
+display \x0058 13467
+display \x00A1 23467
+display \x00A5 123467
+display \x00B5 567
+display \x00A6 1567
+display \x00AC 2567
+display \x005C 12567
+display \x00B0 3567
+display \x005A 13567
+display \x00A9 23567
+display \x00BC 123567
+display \x007F 4567
+display \x00BF 14567
+display \x0057 24567
+display \x005D 124567
+display \x00A3 34567
+display \x0059 134567
+display \x00BE 234567
+display \x00BD 1234567
+display \x00AA 8
+display \x0081 18
+display \x00E2 28
+display \x0082 128
+display \x00E6 38
+display \x008B 138
+display \x00EA 238
+display \x008C 1238
+display \x0080 48
+display \x0083 148
+display \x0089 248
+display \x0086 1248
+display \x00F8 348
+display \x008D 1348
+display \x0093 2348
+display \x0090 12348
+display \x00E3 58
+display \x0085 158
+display \x00EE 258
+display \x0088 1258
+display \x00F2 358
+display \x008F 1358
+display \x00E0 2358
+display \x0092 12358
+display \x009E 458
+display \x0084 1458
+display \x008A 2458
+display \x0087 12458
+display \x00E5 3458
+display \x008E 13458
+display \x0094 23458
+display \x0091 123458
+display \x00F0 68
+display \x00E1 168
+display \x00FB 268
+display \x00E9 1268
+display \x00FE 368
+display \x0095 1368
+display \x00EC 2368
+display \x0096 12368
+display \x00F1 468
+display \x00ED 1468
+display \x009B 2468
+display \x00FD 12468
+display \x00E7 3468
+display \x0098 13468
+display \x00F6 23468
+display \x00E4 123468
+display \x00F5 568
+display \x00FA 1568
+display \x00F4 2568
+display \x009C 12568
+display \x00F9 3568
+display \x009A 13568
+display \x00E8 23568
+display \x00EF 123568
+display \x009F 4568
+display \x00F3 14568
+display \x0097 24568
+display \x009D 124568
+display \x00FF 34568
+display \x0099 134568
+display \x00FC 234568
+display \x00EB 1234568
+display \x00A0 78
+display \x0001 178
+display \x00C2 278
+display \x0002 1278
+display \x00C6 378
+display \x000B 1378
+display \x00CA 2378
+display \x000C 12378
+display \x0000 478
+display \x0003 1478
+display \x0009 2478
+display \x0006 12478
+display \x00D8 3478
+display \x000D 13478
+display \x0013 23478
+display \x0010 123478
+display \x00C3 578
+display \x0005 1578
+display \x00CE 2578
+display \x0008 12578
+display \x00D2 3578
+display \x000F 13578
+display \x00C0 23578
+display \x0012 123578
+display \x001E 4578
+display \x0004 14578
+display \x000A 24578
+display \x0007 124578
+display \x00C5 34578
+display \x000E 134578
+display \x0014 234578
+display \x0011 1234578
+display \x00D0 678
+display \x00C1 1678
+display \x00DB 2678
+display \x00C9 12678
+display \x00DE 3678
+display \x0015 13678
+display \x00CC 23678
+display \x0016 123678
+display \x00D1 4678
+display \x00CD 14678
+display \x001B 24678
+display \x00DD 124678
+display \x00C7 34678
+display \x0018 134678
+display \x00D6 234678
+display \x00C4 1234678
+display \x00D5 5678
+display \x00DA 15678
+display \x00D4 25678
+display \x001C 125678
+display \x00D9 35678
+display \x001A 135678
+display \x00C8 235678
+display \x00CF 1235678
+display \x001F 45678
+display \x00D3 145678
+display \x0017 245678
+display \x001D 1245678
+display \x00DF 345678
+display \x0019 1345678
+display \x00DC 2345678
+display \x00CB 12345678
+
+
=======================================
--- /dev/null
+++ /tests/test_suite/test_14/pagenum.cti       Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,62 @@
+# PAGENUMBERS
+
+digit 1 2
+digit 2 23
+digit 3 25
+digit 4 256
+digit 5 26
+digit 6 235
+digit 7 2356
+digit 8 236
+digit 9 35
+digit 0 356
+litdigit 1 1
+litdigit 2 12
+litdigit 3 14
+litdigit 4 145
+litdigit 5 15
+litdigit 6 124
+litdigit 7 1245
+litdigit 8 125
+litdigit 9 24
+litdigit 0 245
+numsign 3456
+
+# ROMAN NUMBERS
+
+uplow Cc 147,14
+uplow Ii 247,24
+uplow Ll 1237,123
+uplow Mm 1347,134
+uplow Vv 12367,1236
+uplow Xx 13467,1346
+
+# CONTINUATION PAGES
+
+uplow Aa 17,1
+uplow Bb 127,12
+uplow Dd 1457,145
+uplow Ee 157,15
+uplow Ff 1247,124
+uplow Gg 12457,1245
+uplow Hh 1257,125
+uplow Jj 2457,245
+uplow Kk 137,13
+uplow Nn 13457,1345
+uplow Oo 1357,135
+uplow Pp 12347,1234
+uplow Qq 123457,12345
+uplow Rr 12357,1235
+uplow Ss 2347,234
+uplow Tt 23457,2345
+uplow Uu 1367,136
+uplow Ww 24567,2456
+uplow Yy 134567,13456
+uplow Zz 13567,1356
+
+# PRINT PAGES
+
+sign \\ 12567
+sign _ 456
+replace  \\_
+
=======================================
--- /dev/null
+++ /tests/test_suite/test_14/semantics.sem     Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,7 @@
+root                           &xpath(/*)
+p                              &xpath(//p)
+note                           note,id
+noteref                                noteref,id
+notesheader                    notesheader
+notesdescription       notesdescription
+newpage                                newpage
=======================================
--- /dev/null
+++ /tests/test_suite/test_14/styles.cfg        Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,17 @@
+style root
+   braillePageNumberFormat blank
+
+style page
+   newPageBefore yes
+
+style p
+
+style note
+       leftMargin 2
+       firstLineIndent 2
+
+style notesheader
+       format centered
+
+style notesdescription
+       format leftJustified
=======================================
--- /dev/null
+++ /tests/test_suite/test_14/whitespace.cti    Fri Sep 19 15:51:24 2014 UTC
@@ -0,0 +1,9 @@
+# WHITESPACE
+
+space \x0020 0
+space \x0009 0
+space \x000C 0
+space \x000D 0
+space \x000A 0
+space \x00A0 a
+
=======================================
--- /liblouisutdml/Makefile.am  Fri Sep 19 12:15:34 2014 UTC
+++ /liblouisutdml/Makefile.am  Fri Sep 19 15:51:24 2014 UTC
@@ -29,6 +29,7 @@
 liblouisutdml_la_SOURCES = \
        change_table.c \
        makeContents.c \
+       makeEndnotes.c \
        examine_document.c \
        liblouisutdml.c \
        liblouisutdml.h \
=======================================
--- /liblouisutdml/louisutdml.h Wed Jun 18 09:23:57 2014 UTC
+++ /liblouisutdml/louisutdml.h Fri Sep 19 15:51:24 2014 UTC
@@ -76,6 +76,7 @@
   int keep_with_next;
   int dont_split;
   int orphan_control;
+  int widow_control;
   int first_line_indent;       /* At true margin if negative */
   char *translation_table;
   int skip_number_lines;       /*Don't write on lines with page numbers */
@@ -187,6 +188,8 @@
   FormatFor orig_format_for;
   int contents;
   int has_contentsheader;
+  int endnotes;
+  int endnote_stage;
   unsigned int mode;
   unsigned int orig_mode;
   unsigned int config_mode;
@@ -348,6 +351,13 @@
                   translatedLength);
 int finish_heading (sem_act action);
 int make_contents ();
+int initialize_endnotes();
+int make_endnotes();
+int link_endnote(xmlNode* node);
+void set_notes_header();
+void set_notes_description();
+int start_endnote();
+int finish_endnote(xmlNode* node);
 void do_reverse (xmlNode * node);
 int do_boxline (xmlNode * node);
 void do_pagebreak (xmlNode *node);
=======================================
--- /liblouisutdml/readconfig.c Wed Jun 18 09:23:57 2014 UTC
+++ /liblouisutdml/readconfig.c Fri Sep 19 15:51:24 2014 UTC
@@ -713,7 +713,8 @@
     "56",
     "pageNumberTable",
     "57",
-// available     "58",
+       "Endnotes",
+       "58",
 // available    "59",
     "macro",
     "60",
@@ -912,14 +913,6 @@
          configureError (nested, "invalid mathexprTableName");
          return 0;
          }
-         break;
-       case 57:
-         ud->pagenum_table_name = findTable (nested);
-         if (ud->pagenum_table_name == NULL)
-         {
-         configureError (nested, "invalid pageNumberTable");
-         return 0;
-         }
          break;
        case 24:
          topMargin = atof (nested->value);
@@ -1073,8 +1066,18 @@
          if ((k = orValues (nested, configModes)) != NOTFOUND)
            ud->config_mode = k;
          break;
-// available   case 57:
-// available   case 58:
+       case 57:
+         ud->pagenum_table_name = findTable (nested);
+         if (ud->pagenum_table_name == NULL)
+         {
+         configureError (nested, "invalid pageNumberTable");
+         return 0;
+         }
+         break;
+       case 58:
+         if ((k = checkValues (nested, yesNo)) != NOTFOUND)
+           ud->endnotes = k;
+         break;
 // available   case 59:
        case 60:
          new_macro (nested->value, nested->value2);
=======================================
--- /liblouisutdml/sem_enum.h   Wed Jun 18 09:23:57 2014 UTC
+++ /liblouisutdml/sem_enum.h   Fri Sep 19 15:51:24 2014 UTC
@@ -40,6 +40,8 @@
   htmllink,
   htmltarget,
   changetable,
+  /* Endnote position */
+  noteref,
   reverse,
   configfile,
   configstring,
@@ -68,6 +70,10 @@
   contents8,
   contents9,
   contents10,
+  /* Endnotes */
+  note,
+  notesheader,
+  notesdescription,
   /* translation */
   notranslate,
   compbrl,
=======================================
--- /liblouisutdml/sem_names.h  Thu Jun 19 14:55:56 2014 UTC
+++ /liblouisutdml/sem_names.h  Fri Sep 19 15:51:24 2014 UTC
@@ -8,6 +8,7 @@
   "htmllink",
   "htmltarget",
   "changetable",
+  "noteref",
   "reverse",
   "configfile",
   "configstring",
@@ -35,6 +36,9 @@
   "contents8",
   "contents9",
   "contents10",
+  "note",
+  "notesheader",
+  "notesdescription",
   "notranslate",
   "compbrl",
   "uncontracted",
=======================================
--- /liblouisutdml/transcribe_paragraph.c       Wed Jun 18 09:23:57 2014 UTC
+++ /liblouisutdml/transcribe_paragraph.c       Fri Sep 19 15:51:24 2014 UTC
@@ -50,6 +50,9 @@
 static int orphan_control = 0;
 static int orphan_control_pos = 0;
 static int orphan_control_status = 0;
+static int widow_control = 0;
+static int widow_control_pos = 0;
+static int widow_control_status = 0;
 static int saved_text_length;
 static int saved_sync_text_length;
 static int saved_translated_length;
@@ -189,6 +192,7 @@
   int keep_with_next_this = 0;
   int keep_with_previous_this = 0;
   int orphan_control_this = 0;
+  int widow_control_this = 0;
   StyleType *style;
   int haveMacro = 0;
   xmlNode *child;
@@ -309,9 +313,19 @@
       return 1;
     case changetable:
       change_table (node);
-      if (node->children == NULL)
-       return 1;
+ //if (node->children == NULL) ////?? removed, as change_table() cycles through all children anyway, so if changetable has child nodes (ie. <changetable><xyz>Text</xyz><changetable>) then produces duplicate outputs.
+                       return 1;
       break;
+       case noteref:                                                   ////
+               if(ud->endnotes)
+                       start_endnote(node);
+               else
+               {
+                       if(action!=0)
+                               pop_sem_stack();
+                       return 1;
+               }
+               break;
     case pagenum:
       do_pagenum ();
       break;
@@ -368,10 +382,13 @@
                            dont_split_this = 1;
                          else if (style_this->orphan_control > 1)
                            orphan_control_this = style_this->orphan_control;
+                         else if (style_this->widow_control > 1)
+                               widow_control_this = style_this->widow_control;
+
                        }
                      keep_with_next_this = style_this->keep_with_next;
                    }
-                 if (dont_split_this || orphan_control_this)
+                 if (dont_split_this || orphan_control_this || 
widow_control_this)
                    {
                      if (!ud->outbuf3_enabled)
                        {
@@ -397,6 +414,11 @@
                      orphan_control = orphan_control_this;
                      orphan_control_pos = ud->lines_length;
                    }
+                 if (widow_control_this)
+                 {
+                       widow_control = widow_control_this;
+                       widow_control_pos = ud->lines_length;
+                 }
                }
            }
          if (strcmp (child->name, "brl") != 0)
@@ -429,7 +451,8 @@
            {
              if (dont_split_status >= 0 &&
                  keep_with_previous_status >= 0
-                 && orphan_control_status >= 0)
+                 && orphan_control_status >= 0
+                 && widow_control_status >=0)
                {
                  if (keep_with_previous)
                    {
@@ -480,9 +503,32 @@
                      if (i == orphan_control)
                        orphan_control_status = 1;
                    }
+
+                 if (widow_control)
+                   {
+                     if (widow_control_this)
+                               widow_control_status = 1;
+                     else
+                               widow_control_status = 0;
+                     i = ud->lines_length-widow_control_pos-1;
+                     while (i > ud->lines_length-widow_control && i > 0)
+                         {
+                               if (ud->lines_pagenum[widow_control_pos + i] >
+                             ud->lines_pagenum[widow_control_pos + i - 1])
+                           {
+                             if (!ud->lines_newpage[i])
+                                       widow_control_status = -1;
+                             break;
+                           }
+                               i--;
+                         }
+                     if (i == ud->lines_length-widow_control)
+                               widow_control_status = 1;
+                   }
                }
              if (dont_split_status < 0 ||
-                 keep_with_previous_status < 0 || orphan_control_status < 0)
+                 keep_with_previous_status < 0 || orphan_control_status < 0 ||
+                 widow_control_status < 0)
                {
                  if (state_saved)
                    {
@@ -493,6 +539,8 @@
                      keep_with_previous_status = 0;
                      orphan_control = 0;
                      orphan_control_status = 0;
+                         widow_control = 0;
+                         widow_control_status = 0;
                      restoreState ();
                      child = saved_child;
                      branchCount = saved_branchCount;
@@ -519,9 +567,14 @@
                  orphan_control = 0;
                  orphan_control_status = 0;
                }
-             if ((!dont_split && !keep_with_previous &&
-                  !keep_with_next && !orphan_control) || (!child
-                                                          && state_saved))
+               if(widow_control_status > 0)
+               {
+                       widow_control = 0;
+                       widow_control_status = 0;
+               }
+           if ((!dont_split && !keep_with_previous &&
+                  !keep_with_next && !orphan_control
+                  &&!widow_control) ||(!child && state_saved))
                {
                  write_buffer (3, 0);
                  ud->outbuf3_enabled = 0;
@@ -536,6 +589,8 @@
            keep_with_previous = 0;
          if (orphan_control_this)
            orphan_control = 0;
+         if(widow_control_this)
+               widow_control = 0;
        }
     }
   insert_code (node, branchCount);
@@ -557,6 +612,10 @@
        set_footer_string (ud->translated_buffer, ud->translated_length);
        ud->translated_length = 0;
        break;
+       case noteref:
+               if(ud->endnotes)
+                       finish_endnote(node);
+               break;
       default:
        break;
       }
=======================================
--- /liblouisutdml/transcriber.c        Fri Aug 22 08:24:33 2014 UTC
+++ /liblouisutdml/transcriber.c        Fri Sep 19 15:51:24 2014 UTC
@@ -230,6 +230,8 @@
     }
   if (ud->contents && !ud->has_contentsheader)
     initialize_contents ();
+  if(ud->endnotes)
+       initialize_endnotes();
   if (ud->format_for == utd)
     return utd_start ();
   return 1;
@@ -251,6 +253,8 @@
       fillPage ();
       writeOutbuf ();
     }
+  if(ud->endnotes)
+       make_endnotes();
   if (ud->contents)
     make_contents ();
   switch (ud->format_for)
@@ -791,7 +795,8 @@
   }
   if (ud->translated_length > 0 && ud->translated_length <
       MAX_TRANS_LENGTH &&
-      ud->translated_buffer[ud->translated_length - 1] > 32)
+      ud->translated_buffer[ud->translated_length - 1] > 32
+         && ud->text_buffer[0] != 32)
     {
       ud->translated_buffer[ud->translated_length++] = 32;
       if (ud->in_sync)
@@ -1372,12 +1377,13 @@
       pageNumberString[pageNumberLength++] = ' ';
       if (printPageNumber)
        {
-         pageNumberString[pageNumberLength++] = ' ';
+         //pageNumberString[pageNumberLength++] = ' ';
          getPrintPageString ();
        }
       if (braillePageNumber)
        {
-         pageNumberString[pageNumberLength++] = ' ';
+         if(printPageNumber)
+               pageNumberString[pageNumberLength++] = ' ';
          getBraillePageString ();
        }
     }
@@ -2786,6 +2792,8 @@
       int wordTooLong = 0;
       int leadingBlanks = 0;
       int trailingBlanks = 0;
+      int breakAt = 0;
+      int insertHyphen;
       availableCells = startLine ();
       if (styleSpec->status == startBody)
        {
@@ -2797,24 +2805,55 @@
       trailingBlanks = ud->style_right_margin;
       availableCells -= leadingBlanks;
       availableCells -= trailingBlanks;
-      if ((translatedLength - charactersWritten) < availableCells)
+       if(ud->style_format == centered)
        {
-         k = (availableCells - (translatedLength - charactersWritten));
-         if (ud->style_format == centered)
-           k /= 2;
-         else if (ud->style_format != rightJustified)
-           return 0;
-         if (!insertCharacters (blanks, leadingBlanks + k))
-           return 0;
-         if (!insertWidechars (&translatedBuffer[charactersWritten],
-                               translatedLength - charactersWritten))
-           return 0;
-         finishLine ();
-         break;
+               if(pageNumberLength > 0)
+                       availableCells = ud->cells_per_line - 
2*(pageNumberLength);
+               else
+                       availableCells = ud->cells_per_line;
+               availableCells -= leadingBlanks;
+               availableCells -= trailingBlanks;
+
+               if(translatedLength - charactersWritten <= availableCells)
+               {
+                       if(pageNumberLength > 0)
+                       {
+ leadingBlanks += pageNumberLength + (availableCells-(translatedLength - charactersWritten))/2; + trailingBlanks += (availableCells-(translatedLength - charactersWritten))/2;
+                       }
+                       else
+                       {
+ trailingBlanks += (availableCells-(translatedLength - charactersWritten))/2; + leadingBlanks += (availableCells-(translatedLength - charactersWritten))/2;
+                       }
+
+                       if (!insertCharacters (blanks, leadingBlanks))
+                       return 0;
+
+                       if (!insertWidechars(
+ &translatedBuffer[charactersWritten],translatedLength - charactersWritten)
+                                       )
+                       return 0;
+                       finishLine ();
+                       break;
+               }
        }
-      if ((charactersWritten + availableCells) > translatedLength)
-       cellsToWrite = translatedLength - charactersWritten;
-      else
+       else if((translatedLength - charactersWritten) < availableCells)
+       {
+               k = availableCells - (translatedLength - charactersWritten);
+               if (ud->style_format != rightJustified)
+                       return 0;
+               if (!insertCharacters (blanks, leadingBlanks + k))
+                       return 0;
+               if (!insertWidechars(&translatedBuffer[charactersWritten],
+                       translatedLength - charactersWritten))
+               return 0;
+               finishLine ();
+               break;
+       }
+    if ((charactersWritten + availableCells) > translatedLength)
+               cellsToWrite = translatedLength - charactersWritten;
+    else
        {
          for (cellsToWrite = availableCells; cellsToWrite > 0;
               cellsToWrite--)
@@ -2825,15 +2864,36 @@
              cellsToWrite = availableCells - 1;
              wordTooLong = 1;
            }
+               else if(ud->hyphenate)
+                       if(hyphenatex(charactersWritten+cellsToWrite,
+                       charactersWritten + availableCells,
+                       &breakAt,
+                       &insertHyphen))
+                               cellsToWrite = breakAt - charactersWritten;
        }
for (k = charactersWritten; k < (charactersWritten + cellsToWrite); k++)
        if (translatedBuffer[k] == 0xa0)        /*unbreakable space */
          translatedBuffer[k] = 0x20;   /*space */
       if (!wordTooLong)
        {
-         k = availableCells - cellsToWrite;
-         if (ud->style_format == centered)
-           k /= 2;
+               k = availableCells - cellsToWrite;
+               if (ud->style_format == centered)
+               {
+                       availableCells = ud->cells_per_line - 
2*pageNumberLength;
+                       availableCells -= leadingBlanks;
+                       availableCells -= trailingBlanks;
+                       if(pageNumberLength > 0)
+                       {
+                               leadingBlanks += pageNumberLength + 
(availableCells-cellsToWrite)/2;
+                               trailingBlanks += 
(availableCells-cellsToWrite)/2;
+                       }
+                       else
+                       {
+                               trailingBlanks += 
(availableCells-cellsToWrite)/2;
+                               leadingBlanks += 
(availableCells-cellsToWrite)/2;
+                       }
+                       k=0;
+               }
        }
       else
        k = 0;
@@ -2845,12 +2905,10 @@
       charactersWritten += cellsToWrite;
       if (translatedBuffer[charactersWritten] == ' ')
        charactersWritten++;
-      if (wordTooLong)
-       {
-         if (!insertDubChars (ud->lit_hyphen, strlen (ud->lit_hyphen)))
-           return 0;
-       }
-      finishLine ();
+      if ((breakAt && insertHyphen) || wordTooLong)
+               if (!insertDubChars (ud->lit_hyphen, strlen (ud->lit_hyphen)))
+                       return 0;
+    finishLine ();
     }
   return 1;
 }
@@ -2993,6 +3051,29 @@
        getBraillePageString ();
       start_heading (action, translatedBuffer, translatedLength);
     }
+  if(ud->endnotes && action == note && ud->endnote_stage == 1)                 
          ////
+  {
+       link_endnote(styleSpec->node);
+       ud->text_length = ud->translated_length = ud->sync_text_length = 0;
+       return 1;
+  }
+  else if(ud->endnotes && action == notesheader && ud->endnote_stage == 1)
+  {
+       set_notes_header();
+       ud->text_length = ud->translated_length = ud->sync_text_length = 0;
+       return 1;
+  }
+ else if(ud->endnotes && action == notesdescription && ud->endnote_stage == 1)
+  {
+       set_notes_description();
+       ud->text_length = ud->translated_length = ud->sync_text_length = 0;
+       return 1;
+  }
+ else if(!ud->endnotes && (action == note || action == notesheader || action == notesdescription))
+  {
+       ud->text_length = ud->translated_length = ud->sync_text_length = 0;
+       return 1;
+  }
   switch (ud->style_format)
     {
     case centered:
=======================================
--- /tests/test_suite/Makefile.am       Wed Apr  2 12:38:10 2014 UTC
+++ /tests/test_suite/Makefile.am       Fri Sep 19 15:51:24 2014 UTC
@@ -11,5 +11,6 @@
        test_10                                 \
        test_11                                 \
        test_12                                 \
-       test_13
+       test_13                                 \
+       test_14

For a description of the software, to download it and links to
project pages go to http://www.abilitiessoft.com

Other related posts:

  • » [liblouis-liblouisxml] [liblouisutdml] push by mwhapples - Changes by Paul Wood on 2014-09-22 08:48 GMT - liblouisutdml