Here's a patch which is a start at importing lists from WordPerfect into 
AbiWord. It supports both numbered and bulleted lists, with multiple levels 
of nesting. 

There are some issues regarding nested lists here. With WordPerfect, you can 
have lists of the following format:

1.
        i.
                a.

AbiWord doesn't support these, and gives this type of output when you try to 
do this:

1.
        1.i.
                1.i.a.

This needs to be fixed at some point. The current behaviour that I have set 
is to handle such lists as follows:

1.
        1.1.
                1.1.1.

(as one might expect)

There's other weirdness involved in the importing process: 
- WordPerfect sets list delimiters "on the fly", instead of in the list 
definition (I get around this by updating AbiWord's list definition on the 
fly, probably a sub-optimal solution).
- WordPerfect sets custom bullets (e.g.: diamonds instead of circles) on the 
fly. I will look into fixing this later.

By and large though, the patch improves the usability of AbiWord w.r.t. 
WordPerfect files nicely. I recommend that it only be committed to head 
though (I made the diff against head), to give us time plenty of time to let 
it be thoroughly tested and iron out the kinks, both in the importer and 
AbiWord's (good, but imho far too limited) lists facility.

Regards,

William Lachance
[EMAIL PROTECTED]
--- ie_imp_WordPerfectMetadata.h	Sat Jun  8 04:00:11 2002
+++ ie_imp_WordPerfect.h	Sat Jun  8 13:23:52 2002
@@ -1,6 +1,6 @@
 /* AbiWord
  * Copyright (C) 2001 AbiSource, Inc.
- * Copyright (C) 2001 William Lachance ([EMAIL PROTECTED])
+ * Copyright (C) 2001-2002 William Lachance ([EMAIL PROTECTED])
  * Copyright (C) 2002 Marc Maurer ([EMAIL PROTECTED])
  * 
  * This program is free software; you can redistribute it and/or
@@ -33,9 +33,13 @@
 #include "ie_exp.h"
 #include "ie_exp_WordPerfect.h"
 
+#include "ut_string.h"
+#include "ut_string_class.h"
+
 #include "ut_growbuf.h"
 #include "ut_mbtowc.h"
 #include "pd_Document.h"
+#include "fl_AutoNum.h"
 
 // The importer/reader for WordPerfect 6 documents.
 
@@ -70,6 +74,13 @@
 #define WP_INDEX_HEADER_EXTENDED_DOCUMENT_SUMMARY_DESCRIPTOR_POOL 0x12
 #define WP_INDEX_HEADER_CHECK_AS_YOU_GO_DESCRIPTOR_POOL 0x4E
 
+#define WP_INDEX_HEADER_OUTLINE_STYLE 49 // 0x31
+#define WP_INDEX_HEADER_OUTLINE_STYLE_ARABIC_NUMBERING 0
+#define WP_INDEX_HEADER_OUTLINE_STYLE_LOWERCASE_NUMBERING 1
+#define WP_INDEX_HEADER_OUTLINE_STYLE_UPPERCASE_NUMBERING 2
+#define WP_INDEX_HEADER_OUTLINE_STYLE_LOWERCASE_ROMAN_NUMBERING 3
+#define WP_INDEX_HEADER_OUTLINE_STYLE_UPPERCASE_ROMAN_NUMBERING 4
+
 #define WP_TOP_SOFT_SPACE 128
 #define WP_TOP_HARD_HYPHEN 132 // (0x84)
 #define WP_TOP_DORMANT_HARD_RETURN 135 // (0x87)
@@ -107,6 +118,7 @@
 #define WP_CHARACTER_GROUP_FONT_SIZE_CHANGE 27 // 0x1b
 
 #define WP_PARAGRAPH_GROUP_JUSTIFICATION 5 // 0x05
+#define WP_PARAGRAPH_GROUP_OUTLINE_DEFINE 14 // 0x0e
 #define WP_PARAGRAPH_GROUP_JUSTIFICATION_LEFT 0
 #define WP_PARAGRAPH_GROUP_JUSTIFICATION_FULL 1
 #define WP_PARAGRAPH_GROUP_JUSTIFICATION_CENTER 2
@@ -114,9 +126,31 @@
 #define WP_PARAGRAPH_GROUP_JUSTIFICATION_FULL_ALL_LINES 4
 #define WP_PARAGRAPH_GROUP_JUSTIFICATION_RESERVED 5
 
+#define WP_STYLE_GROUP_PARASTYLE_BEGIN_ON_PART1 4 // 0x04
+#define WP_STYLE_GROUP_PARASTYLE_BEGIN_OFF_PART1 5 // 0x05
+#define WP_STYLE_GROUP_PARASTYLE_BEGIN_ON_PART2 6 // 0x06
+#define WP_STYLE_GROUP_PARASTYLE_BEGIN_OFF_PART2 7 // 0x07
+#define WP_STYLE_GROUP_PARASTYLE_END_ON 8 // 0x08
+#define WP_STYLE_GROUP_PARASTYLE_END_OFF 9 // 0x09
+
+#define WP_PARAGRAPH_GROUP_OUTLINE_DEFINE_BULLETED_NUMBERING 0
+#define WP_PARAGRAPH_GROUP_OUTLINE_DEFINE_ARABIC_NUMBERING 256
+#define WP_PARAGRAPH_GROUP_OUTLINE_DEFINE_LOWERCASE_NUMBERING 3
+#define WP_PARAGRAPH_GROUP_OUTLINE_DEFINE_LOWERCASE_ROMAN_NUMBERING 769
+
+#define WP_CHARACTER_GROUP_PARAGRAPH_NUMBER_ON 50 // 0x32
+#define WP_CHARACTER_GROUP_PARAGRAPH_NUMBER_OFF 51 // 0x33
+
+#define WP_DISPLAY_NUMBER_REFERENCE_GROUP_PARAGRAPH_NUMBER_DISPLAY_ON 12
+#define WP_DISPLAY_NUMBER_REFERENCE_GROUP_PARAGRAPH_NUMBER_DISPLAY_OFF 13
+
 #define WP_BOX_GROUP_NUM_RESERVED_BYTES 14
 #define WP_BOX_GROUP_OVERRIDE_FLAGS_BOX_CONTENT 8192
 
+#define WP_NUM_LIST_LEVELS 8
+// These are the defaults for generating list text
+#define WP_PARAGRAPH_STYLE_MARGIN_LEFT_INCREMENT 0.5f // I have no idea if this is correct, but it seems to look reasonably good
+#define WP_PARAGRAPH_STYLE_TEXT_INDENT_DECREMENT -0.3f // I have no idea if this is correct, but it seems to look reasonably good
 // Character properties
 class ABI_EXPORT WordPerfectTextAttributes
 {
@@ -214,6 +248,37 @@
    bool m_hasChildren;
 };
 
+//struct WordPerfectParagraphStyleProperties
+//{
+//};
+
+
+class ABI_EXPORT WordPerfectListDefinition
+{
+ public:
+   WordPerfectListDefinition(UT_uint16 outlineHash, unsigned char *packetNumberingMethods); // update list types based on information from a wordperfect outline define packet
+   UT_uint16 getOutlineHash() { return m_outlineHash; }
+   void setListID(int level, UT_uint32 id) { m_listIDs[level] = id; }
+   UT_uint32 getListID(int level) { return m_listIDs[level]; }
+   UT_uint16 getListNumber(int level) { return m_currentListNumbers[level]; }
+   List_Type getListType(int level) { return m_listTypes[level]; }
+   bool isLevelNumbered(int level) { return m_bIsNumberedList[level]; }
+   UT_String getListDelim(int level) { return m_listDelim[level]; }
+   
+   void setListRightDelimText(int level, UT_String rightDelimText) { UT_String_sprintf(m_listDelim[level], "%%L%s", rightDelimText.c_str()); }
+   void resetListIDsAndNumbers() { for (unsigned int i=0; i<WP_NUM_LIST_LEVELS; i++) { m_listIDs[i]=0; m_currentListNumbers[i]=0; } }
+   void updateListTypes(UT_uint16 *numberingMethods); // update list types based on information from a wordperfect outlining group
+   void incrementLevelNumber(int level) { m_currentListNumbers[level]++; }
+	
+ private:
+   UT_uint16 m_outlineHash; // we're not actually hashing, but we use the hash to identify the outline style
+   UT_uint32 m_listIDs[WP_NUM_LIST_LEVELS];
+   List_Type m_listTypes[WP_NUM_LIST_LEVELS];
+   bool m_bIsNumberedList[WP_NUM_LIST_LEVELS];
+   UT_uint16 m_currentListNumbers[WP_NUM_LIST_LEVELS];
+   UT_String m_listDelim[WP_NUM_LIST_LEVELS];
+};
+
 class ABI_EXPORT IE_Imp_WordPerfect_Sniffer : public IE_ImpSniffer
 {
 	friend class IE_Imp;
@@ -247,6 +312,7 @@
    UT_Error _parseIndexHeader();
    UT_Error _parseFontDescriptorPacket(int packetID, UT_uint32 dataPacketSize, UT_uint32 dataPointer);
    UT_Error _parseDocumentInformationDescriptorPacket(int packetID, UT_uint32 dataPacketSize, UT_uint32 dataPointer);
+   UT_Error _parseOutlineStylePacket(int packetID, UT_uint32 dataPacketSize, UT_uint32 dataPointer);
    UT_Error _handleBoxGroupTemplate(int boxGroupTemplatePID);
    UT_Error _handleBoxGroupContent(int boxContentPID);
    UT_Error _handleGraphicsData(int graphicPID);
@@ -259,6 +325,7 @@
    UT_Error _handleColumnGroup();
    UT_Error _handleParagraphGroup();
    UT_Error _handleParagraphGroupJustification();
+   UT_Error _handleOutlineDefine();
    UT_Error _handleSetNumberGroup();
    UT_Error _handleNumberingMethodGroup();
    UT_Error _handleDisplayNumberReferenceGroup();
@@ -284,10 +351,13 @@
    UT_Error _skipGroup(long startPosition, UT_uint16 groupSize);
    UT_Error _appendCurrentTextProperties();
    UT_Error _appendCurrentParagraphProperties();
+   UT_Error _appendCurrentListProperties();
+   WordPerfectListDefinition * _getListDefinition(UT_uint16 outlineHash);
+   UT_Error _updateDocumentListDefinition(WordPerfectListDefinition *listDefinition, int level);
    UT_Error _flushText();
    UT_Error _flushParagraph();
-   UT_Error _appendSection() ;
-
+   UT_Error _appendSection();
+   
  private:
    FILE *m_importFile;
    UT_uint32 m_documentEnd;
@@ -300,25 +370,41 @@
    bool m_bSectionChanged;
    bool m_bParagraphInSection;
    bool m_bFirstMargin;
+   enum WordPerfectParagraphStyleState { notInStyle, beginPart1, beginPart2BeforeNumbering, beginPart2Numbering, beginPart2DisplayReferencing, beginPart2AfterNumbering, styleBody, end };
+   WordPerfectParagraphStyleState m_paragraphStyleState;
+   bool m_bPutativeListHasParagraphNumber;
+   UT_uint32 m_currentListTag;
+   UT_String m_rightListDelim; // (AFAIK WP doesn't do left delimiters on lists?)
+   bool m_bEnteringList;
+   
    UT_Mbtowc m_Mbtowc;
    UT_GrowBuf m_textBuf;
    UT_Vector m_fontDescriptorList;
    UT_Vector m_headerPacketList;
    UT_Vector m_wordPerfectDispatchBytes;
+   UT_Vector m_listDefinitionList;
    WordPerfectTextAttributes m_textAttributes;
    WordPerfectParagraphProperties m_paragraphProperties;
 
+   int m_numDeferredParagraphBreaks;
+   
    float m_leftMargin;
    float m_rightMargin;
    bool m_bLeftMarginSet;
    bool m_bRightMarginSet;
    unsigned char m_numberOfColumns;
    bool m_bColumnsSet;
+   
+   unsigned char m_currentListLevel; // WordPerfect list levels start at 0, Abi list levels start at 1
+   UT_uint16 m_currentOutlineHash;
+   
+   float m_paragraphStyleTextIndent;
+   float m_paragraphStyleMarginLeft;
 };
 
 struct ABI_EXPORT WordPerfectByteTag
 {
-   WordPerfectByteTag( unsigned char byte, UT_Error (IE_Imp_WordPerfect::*func)() );   
+   WordPerfectByteTag( unsigned char byte, UT_Error (IE_Imp_WordPerfect::*func)() );
    unsigned char m_byte;
    UT_Error (IE_Imp_WordPerfect::*m_func) () ;
 }; 
--- ie_imp_WordPerfectMetadata.cpp	Sat Jun  8 03:59:57 2002
+++ ie_imp_WordPerfect.cpp	Sat Jun  8 04:54:44 2002
@@ -1,6 +1,6 @@
 /* AbiWord
  * Copyright (C) 2001 AbiSource, Inc.
- * Copyright (C) 2001 William Lachance ([EMAIL PROTECTED])
+ * Copyright (C) 2001-2002 William Lachance ([EMAIL PROTECTED])
  * Copyright (C) 2002 Marc Maurer ([EMAIL PROTECTED])
  * 
  * This program is free software; you can redistribute it and/or
@@ -38,6 +38,7 @@
 #include "ut_assert.h"
 #include "ut_debugmsg.h"
 #include "ut_math.h" // for rint (font size)
+#include "ut_rand.h"
 
 #include "xap_Frame.h"
 #include "xap_EncodingManager.h"
@@ -45,15 +46,22 @@
 #include "pd_Document.h"
 #include "pt_Types.h"
 
+#include "fl_AutoLists.h"
+#include "fl_AutoNum.h"
+
 #include "ap_Strings.h"
 
 #include "ie_imp_WordPerfect.h"
 
+
 #define X_CheckFileError(v) if (v==EOF) { UT_DEBUGMSG(("X_CheckFileError: %d\n", __LINE__)); return UT_IE_IMPORTERROR; }
 #define X_CheckFileReadElementError(v) if (v != 1) { UT_DEBUGMSG(("X_CheckFileReadElementError: %d\n", __LINE__)); return UT_IE_IMPORTERROR; } // makes sure that one element is read
 #define X_CheckDocumentError(v) if (!v) { UT_DEBUGMSG(("X_CheckDocumentError: %d\n", __LINE__)); return UT_IE_IMPORTERROR; }
 #define X_CheckWordPerfectError(v) if ((v != UT_OK)) { UT_DEBUGMSG(("X_CheckWordPerfectError: %d\n", __LINE__)); return UT_IE_IMPORTERROR; }
 
+// This should probably be defined in pt_Types.h
+static const UT_uint32 PT_MAX_ATTRIBUTES = 8;
+
 WordPerfectTextAttributes::WordPerfectTextAttributes()
 {
    m_extraLarge = false;
@@ -133,6 +141,73 @@
    m_hasChildren = hasChildren;
 }
 
+WordPerfectListDefinition::WordPerfectListDefinition(UT_uint16 outlineHash, unsigned char *numberingMethods)
+{
+   m_outlineHash = outlineHash;
+   for (unsigned int i=0; i<WP_NUM_LIST_LEVELS; i++)
+     {
+	m_listIDs[i] = 0;
+	m_currentListNumbers[i]=0;
+	UT_String_sprintf(m_listDelim[i], "%%L");
+	switch (numberingMethods[i])
+	  {
+	   case WP_INDEX_HEADER_OUTLINE_STYLE_ARABIC_NUMBERING:
+	     m_listTypes[i] = NUMBERED_LIST; 
+	     m_bIsNumberedList[i] = true;
+	     break;
+	   case WP_INDEX_HEADER_OUTLINE_STYLE_LOWERCASE_NUMBERING:
+	     m_listTypes[i] = LOWERCASE_LIST; //listTypes[i];
+	     m_bIsNumberedList[i] = true;
+	     break;
+	   case WP_INDEX_HEADER_OUTLINE_STYLE_UPPERCASE_NUMBERING:
+	     m_listTypes[i] = UPPERCASE_LIST; //listTypes[i];
+	     m_bIsNumberedList[i] = true;
+	     break;
+	   case WP_INDEX_HEADER_OUTLINE_STYLE_LOWERCASE_ROMAN_NUMBERING:
+	     m_listTypes[i] = LOWERROMAN_LIST; //listTypes[i];
+	     m_bIsNumberedList[i] = true;
+	     break;
+	   case WP_INDEX_HEADER_OUTLINE_STYLE_UPPERCASE_ROMAN_NUMBERING:
+	     m_listTypes[i] = UPPERROMAN_LIST; //listTypes[i];
+	     m_bIsNumberedList[i] = true;
+	     break;
+	   default: // something we're not handling yet (we may yet be able to get a more accurate spec from an outline paragraph group, later)
+	     m_listTypes[i] = BULLETED_LIST; //listTypes[i];
+	     m_bIsNumberedList[i] = false;
+	  }   
+     }
+   
+}
+
+void WordPerfectListDefinition::updateListTypes(UT_uint16 *numberingMethods)
+{
+   for (unsigned int i=0; i<WP_NUM_LIST_LEVELS; i++)
+     {	   
+	switch (numberingMethods[i])
+	  {
+	   case WP_PARAGRAPH_GROUP_OUTLINE_DEFINE_BULLETED_NUMBERING:
+	     m_listTypes[i] = BULLETED_LIST; //listTypes[i];
+	     m_bIsNumberedList[i] = false;
+	     break;
+	   case WP_PARAGRAPH_GROUP_OUTLINE_DEFINE_ARABIC_NUMBERING:
+	     m_listTypes[i] = NUMBERED_LIST; 
+	     m_bIsNumberedList[i] = true;
+	     break;
+	   case WP_PARAGRAPH_GROUP_OUTLINE_DEFINE_LOWERCASE_NUMBERING:
+	     m_listTypes[i] = LOWERCASE_LIST; 
+	     m_bIsNumberedList[i] = true;
+	     break;
+	   case WP_PARAGRAPH_GROUP_OUTLINE_DEFINE_LOWERCASE_ROMAN_NUMBERING:
+	     m_listTypes[i] = LOWERROMAN_LIST; //listTypes[i];
+	     m_bIsNumberedList[i] = true;
+	     break;
+	   default: // something we're not handling yet (fall back on default)
+	     break;
+	  }   
+     }
+}
+
+
 /****************************************************************************/
 /****************************************************************************/
 
@@ -215,7 +290,9 @@
    m_bRightMarginSet = false;
    m_numberOfColumns = 1;
    m_bColumnsSet = false;
-
+   m_paragraphStyleState = notInStyle;
+   m_numDeferredParagraphBreaks = 0;
+   
    m_wordPerfectDispatchBytes.addItem(new WordPerfectByteTag(WP_TOP_SOFT_EOL, &IE_Imp_WordPerfect::_insertSpace));
    m_wordPerfectDispatchBytes.addItem(new WordPerfectByteTag(WP_TOP_SOFT_SPACE, &IE_Imp_WordPerfect::_insertSpace));
    m_wordPerfectDispatchBytes.addItem(new WordPerfectByteTag(WP_TOP_HARD_HYPHEN, &IE_Imp_WordPerfect::_insertHyphen));
@@ -250,6 +327,7 @@
 {
    UT_VECTOR_PURGEALL(WordPerfectFontDescriptor *, m_fontDescriptorList);
    UT_VECTOR_PURGEALL(WordPerfectHeaderPacket *, m_headerPacketList);
+   UT_VECTOR_PURGEALL(WordPerfectListDefinition *, m_listDefinitionList);
 }
 
 /****************************************************************************/
@@ -361,8 +439,11 @@
 	     X_CheckWordPerfectError(_parseFontDescriptorPacket(i, dataPacketSize, dataPointer));
 	     break;
 	   case WP_INDEX_HEADER_EXTENDED_DOCUMENT_SUMMARY_DESCRIPTOR_POOL:
-		 X_CheckWordPerfectError(_parseDocumentInformationDescriptorPacket(i, dataPacketSize, dataPointer));
-		 break;
+	     X_CheckWordPerfectError(_parseDocumentInformationDescriptorPacket(i, dataPacketSize, dataPointer));
+	     break;
+	   case WP_INDEX_HEADER_OUTLINE_STYLE:
+	     X_CheckWordPerfectError(_parseOutlineStylePacket(i, dataPacketSize, dataPointer));
+	     break;
 	   default:
 	     break;
 	  }
@@ -425,6 +506,46 @@
    m_fontDescriptorList.addItem(fontDescriptor); // todo: check for error? how?
    
    if (fseek(m_importFile, (long) (lastPosition), SEEK_SET) != 0)
+     return UT_IE_IMPORTERROR;   
+   
+   return UT_OK;
+}
+
+UT_Error IE_Imp_WordPerfect::_parseOutlineStylePacket(int packetID, UT_uint32 dataPacketSize, UT_uint32 dataPointer)
+{
+   UT_DEBUGMSG(("WordPerfect: Parsing an Outline Style Packet\n"));
+   UT_uint32 lastPosition = ftell(m_importFile);
+   
+   if (fseek(m_importFile, (long) (dataPointer), SEEK_SET) != 0)
+     return UT_IE_IMPORTERROR;
+
+   UT_uint16 numPIDs;
+   UT_uint16 paragraphStylePIDs[WP_NUM_LIST_LEVELS]; // seemingly useless
+   UT_uint16 nonDeletableInfoSize;
+   UT_uint16 definitionHash;
+   unsigned char numberingMethods[WP_NUM_LIST_LEVELS];
+   unsigned char outlineFlags;
+   unsigned char tabBehaviourFlag;
+      
+   X_CheckFileReadElementError(fread(&numPIDs, sizeof(UT_uint16), 1, m_importFile));
+   for (unsigned int i=0; i<WP_NUM_LIST_LEVELS; i++) 
+     X_CheckFileReadElementError(fread(&paragraphStylePIDs[i], sizeof(UT_uint16), 1, m_importFile)); // seemingly useless
+   X_CheckFileReadElementError(fread(&outlineFlags, sizeof(unsigned char), 1, m_importFile));
+   X_CheckFileReadElementError(fread(&definitionHash, sizeof(UT_uint16), 1, m_importFile)); // this is how we identify the list an element may belong to
+   for (unsigned int i=0; i<WP_NUM_LIST_LEVELS; i++)  
+     X_CheckFileReadElementError(fread(&numberingMethods[i], sizeof(unsigned char), 1, m_importFile));
+   //X_CheckFileReadElementError(fread(&tabBehaviourFlag, sizeof(unsigned char), 1, m_importFile));
+   
+   UT_DEBUGMSG(("WordPerfect: Read Outline Style Packet (numPrefixIDs: %i, outlineStylePID: %i, definitionHash: %i, outlineFlags: %s)\n", (int) numPIDs, (int) definitionHash, (int) outlineFlags));
+   UT_DEBUGMSG(("WordPerfect: Read Outline Style Packet (paragraphStylePIDs: %i %i %i %i %i %i %i %i)\n", paragraphStylePIDs[0], paragraphStylePIDs[1], paragraphStylePIDs[2], paragraphStylePIDs[3],
+		paragraphStylePIDs[4], paragraphStylePIDs[5], paragraphStylePIDs[6], paragraphStylePIDs[7]));
+   UT_DEBUGMSG(("WordPerfect: Read Outline Style Packet (numberingMethods: %i %i %i %i %i %i %i %i)\n", numberingMethods[0], numberingMethods[1], numberingMethods[2], numberingMethods[3],
+		numberingMethods[4], numberingMethods[5], numberingMethods[6], numberingMethods[7]));
+   
+   WordPerfectListDefinition *listDefinition = new WordPerfectListDefinition(definitionHash, numberingMethods);
+   m_listDefinitionList.addItem((void *)listDefinition);
+   
+   if (fseek(m_importFile, (long) (lastPosition), SEEK_SET) != 0)
      return UT_IE_IMPORTERROR;
    
    return UT_OK;
@@ -611,20 +732,32 @@
 	int readVal = fgetc(m_importFile);
 	X_CheckFileError(readVal);
 	
-	if(readVal > 32 && readVal < 127 && !m_undoOn) // Standard ASCII characters
-	  {
-	     //UT_DEBUGMSG((" current char = %c \n",(char)readVal));
-	     UT_GrowBufElement wc = (UT_GrowBufElement) readVal;
-	     m_textBuf.append(&wc, 1);
-	  }
-	else if(readVal > 0 && readVal < 32 && !m_undoOn) // International Characters
+	if(readVal > 0 && readVal < 127 && !m_undoOn && m_paragraphStyleState != beginPart2BeforeNumbering && m_paragraphStyleState != beginPart2DisplayReferencing && m_paragraphStyleState !=end) // Standard ASCII characters
 	  {
-	     UT_GrowBufElement internationalCharacter = (UT_GrowBufElement) wp_internationalCharacterMapping[(readVal-1)];
-	     m_textBuf.append( &internationalCharacter, 1);	     
+	     // FIXME: probably not the smartest move to put a comparison here
+	     if (m_paragraphStyleState == beginPart2Numbering)
+	       {
+		  UT_DEBUGMSG(("WordPerfect: Character during numbering.. assuming right delim\n"));
+		  UT_UCS4Char wc = (UT_UCS4Char) readVal;
+		  m_rightListDelim+=wc;
+		  // (AFAIK WP doesn't do left delimiters on bullets?)
+		  //if (m_paragraphStyleState == beginPart2BeforeNumbering)
+		  //  m_leftListDelim+=wc;
+		  //else
+	       }
+	     else
+	       {
+		  UT_GrowBufElement wc;
+		  if (readVal < 32) // International Characters
+		    wc = (UT_GrowBufElement) wp_internationalCharacterMapping[(readVal-1)];
+		  else // normal ASCII characters
+		    wc = (UT_GrowBufElement) readVal;
+		  m_textBuf.append(&wc, 1);
+	       }
+	     
 	  }
 	else 
-	  {
-	     
+	  {	     
 	     for (unsigned int i=0; i<m_wordPerfectDispatchBytes.size(); i++)
 	       {
 		  WordPerfectByteTag *dispatchByte = (WordPerfectByteTag *) m_wordPerfectDispatchBytes.getNthItem( i );
@@ -632,15 +765,15 @@
 		    {
 		       (*this.*(dispatchByte->m_func)) ();
 		       break;
-		    }	  
+		    }
 	       }
 	  }
      }
   
-   UT_DEBUGMSG(("WordPerfect: File Pointer at %i equals or exceeds document length of %i\n", (int)ftell(m_importFile), (int)m_documentEnd));
-   
+   UT_DEBUGMSG(("WordPerfect: File Pointer at %i equals or exceeds document length of %i\n", (int)ftell(m_importFile), (int)m_documentEnd));      
+
    X_CheckWordPerfectError(_flushText());
-   
+
    return UT_OK;
 }
 
@@ -670,16 +803,18 @@
 {
    // (TODO: eliminate a prev space if it's just before this)
    UT_DEBUGMSG(("WordPerfect: Handling a hard EOL \n"));
-   if(!m_undoOn)
-   {
-        if (!m_bParagraphChanged)
+   if(!m_undoOn && m_paragraphStyleState != end)
+   {      
+      // it's a sure sign that we've hit the end of a list if we do a hard end of line inside of one
+      if (!m_bParagraphChanged) 
         {
-            X_CheckWordPerfectError(_flushText());
-            _appendCurrentParagraphProperties();
+	   UT_DEBUGMSG(("WordPerfect: Going with option 1\n"));
+	   X_CheckWordPerfectError(_flushText());
+	   m_numDeferredParagraphBreaks++;
         }
         else
         {
-            X_CheckWordPerfectError(_flushText());
+	   X_CheckWordPerfectError(_flushText());
         }
    }
    
@@ -698,11 +833,11 @@
    long startPosition = ftell(m_importFile);
 
    X_CheckFileReadElementError(fread(&subGroup, sizeof(unsigned char), 1, m_importFile));
-   X_CheckFileReadElementError(fread(&size, sizeof(UT_uint16), 1, m_importFile)); // I have no idea WHAT this var. does. but it's there.
+   X_CheckFileReadElementError(fread(&size, sizeof(UT_uint16), 1, m_importFile));
 
    UT_GrowBufElement wc = 0;
 
-   if(!m_undoOn)
+   if(!m_undoOn && m_paragraphStyleState != beginPart2BeforeNumbering && m_paragraphStyleState != beginPart2Numbering && m_paragraphStyleState !=end)
      {
 	switch(subGroup)
 	  {
@@ -767,7 +902,7 @@
 }
 
 // handles a column group
-// (TODO: partially implemented
+// (TODO: partially implemented)
 UT_Error IE_Imp_WordPerfect::_handleColumnGroup()
 {
    UT_DEBUGMSG(("WordPerfect: Handling a column group\n"));
@@ -778,7 +913,7 @@
 
    X_CheckWordPerfectError(_handleVariableGroupHeader(startPosition, subGroup, size, flags));
     
-   if(!m_undoOn)
+   if(!m_undoOn && m_paragraphStyleState != beginPart2BeforeNumbering && m_paragraphStyleState != beginPart2Numbering && m_paragraphStyleState !=end)
    {
        UT_DEBUGMSG(("WordPerfect: Column subgroup: %d\n", subGroup));
 
@@ -903,22 +1038,29 @@
    long startPosition;
    unsigned char subGroup, flags;
    UT_uint16 size;
-   UT_uint16 nonDeletableInfoSize;
 
    X_CheckWordPerfectError(_handleVariableGroupHeader(startPosition, subGroup, size, flags));   
-   X_CheckFileReadElementError(fread(&nonDeletableInfoSize, sizeof(UT_uint16), 1, m_importFile));
 
    // dispatch to subgroup to handle the rest of the relevant properties within the
    // group (and thus, read more of the file-- so we keep this even if undo is 'on')
-   switch (subGroup)
-   {
-      case WP_PARAGRAPH_GROUP_JUSTIFICATION:
-      {   
-         X_CheckWordPerfectError(_handleParagraphGroupJustification());
-         m_bParagraphChanged = true;
-	      break;
-      }   
-   }
+   if (!m_undoOn && m_paragraphStyleState != beginPart2BeforeNumbering && m_paragraphStyleState != beginPart2Numbering && m_paragraphStyleState !=end)
+     {			
+	switch (subGroup)
+	  {
+	   case WP_PARAGRAPH_GROUP_JUSTIFICATION:
+	       {   
+		  X_CheckWordPerfectError(_handleParagraphGroupJustification());
+		  m_bParagraphChanged = true;
+		  break;
+	       }
+	   case WP_PARAGRAPH_GROUP_OUTLINE_DEFINE:
+	       {
+		  UT_DEBUGMSG(("WordPerfect: LISTS: Outline Define\n"));
+		  X_CheckWordPerfectError(_handleOutlineDefine());		  
+		  break;
+	       }  
+	  }
+     }   
      
    X_CheckWordPerfectError(_skipGroup(startPosition, size));
    
@@ -927,7 +1069,7 @@
 
 
 // handles a style group
-// (TODO: not implemented, just skips over it)
+// (partially implemented, handles stuff which is relevant to list properties being set)
 UT_Error IE_Imp_WordPerfect::_handleStyleGroup()
 {
    UT_DEBUGMSG(("WordPerfect: Handling a style group\n"));
@@ -937,6 +1079,53 @@
    unsigned char flags;
 
    X_CheckWordPerfectError(_handleVariableGroupHeader(startPosition, subGroup, size, flags));   
+   
+   if (!m_undoOn) 
+     {	
+	switch (subGroup) 
+	  {
+	   case WP_STYLE_GROUP_PARASTYLE_BEGIN_ON_PART1:
+	     UT_DEBUGMSG(("WordPerfect: Handling para style begin 1 (ON)\n"));
+	     if (m_numDeferredParagraphBreaks > 0) // wordperfect does not consider that a list may cause a paragraph break. we do.
+	       m_numDeferredParagraphBreaks--;
+	     if (m_bParagraphExists) // (if to handle scary case where we start with a paragraph style sequence)
+	       X_CheckWordPerfectError(_flushText()); // flush anything that came before this (especially eol breaks)
+	     m_paragraphStyleState=beginPart1;
+	     m_paragraphStyleMarginLeft = WP_PARAGRAPH_STYLE_MARGIN_LEFT_INCREMENT; 
+	     m_paragraphStyleTextIndent = WP_PARAGRAPH_STYLE_TEXT_INDENT_DECREMENT; // WL: this is abi's default (not wordperfect's) -- I think it is better to use abi's
+	     m_bPutativeListHasParagraphNumber = false;
+	     break;
+	   case WP_STYLE_GROUP_PARASTYLE_BEGIN_OFF_PART1:
+	     UT_DEBUGMSG(("WordPerfect: Handling a para style begin 1 (OFF)\n"));
+	     break;
+	   case WP_STYLE_GROUP_PARASTYLE_BEGIN_ON_PART2:
+	     UT_DEBUGMSG(("WordPerfect: Handling a para style begin 2 (ON)\n"));
+	     m_paragraphStyleState = beginPart2BeforeNumbering;
+	     break;
+	   case WP_STYLE_GROUP_PARASTYLE_BEGIN_OFF_PART2:
+	     UT_DEBUGMSG(("WordPerfect: Handling a para style begin 2 (OFF)\n"));
+	     m_paragraphStyleState = styleBody;
+	     if (m_bPutativeListHasParagraphNumber) 
+	       {		  
+		  X_CheckWordPerfectError(_appendCurrentListProperties());
+	       }	     
+	     break;
+	   case WP_STYLE_GROUP_PARASTYLE_END_ON:
+	     UT_DEBUGMSG(("WordPerfect: Handling a para style end (ON)\n"));
+	     m_paragraphStyleState = end;
+	     break;
+	   case WP_STYLE_GROUP_PARASTYLE_END_OFF:
+	     UT_DEBUGMSG(("WordPerfect: Handling a parastyle end (OFF)\n"));
+	     if(m_textBuf.getLength() > 0) // don't paste ANYTHING if this paragraph style doesn't have any content
+	       {		  
+		  X_CheckWordPerfectError(_flushText()); // flush the list item text
+	       }
+	     m_paragraphStyleState = notInStyle;
+	     m_numDeferredParagraphBreaks++;
+	     break;
+	  }
+     }   
+   
    X_CheckWordPerfectError(_skipGroup(startPosition, size));
    
    return UT_OK;
@@ -980,8 +1169,18 @@
 	   case 26: // 11010b = decimal tab
 	     // TODO: fix stupid default implementation of adding just a TAB char without looking what it actually should be
 	     {
-		UT_GrowBufElement wc = '\t';
-	        m_textBuf.append(&wc, 1);
+		// we handle things a bit differently in certain parts of wordperfect list parsing
+		if (m_paragraphStyleState == beginPart1 || m_paragraphStyleState == beginPart2BeforeNumbering)
+		  {
+		     UT_DEBUGMSG(("WordPerfect: Incrementing paragraph style margin left\n"));		     
+		     m_paragraphStyleMarginLeft += WP_PARAGRAPH_STYLE_MARGIN_LEFT_INCREMENT;
+		  }	     
+		else 
+		  {
+		     UT_GrowBufElement wc = '\t';
+		     m_textBuf.append(&wc, 1);
+		  }
+		
 	     }
 	     break;
 	   default: // something else shouldn't be possible according to the documentation
@@ -1054,7 +1253,7 @@
    return UT_OK;
 }
 
-// handles a numbering method group
+// handles a number  method group
 // (TODO: not implemented, just skips over it)
 UT_Error IE_Imp_WordPerfect::_handleNumberingMethodGroup()
 {
@@ -1070,16 +1269,31 @@
 }
 
 
-// handles a display number reference group
-// (TODO: not implemented, just skips over it)
+// handles a display number reference group: which, as of now, we just use to determine
+// where a list bullet starts and ends (but only for numbered lists..)
 UT_Error IE_Imp_WordPerfect::_handleDisplayNumberReferenceGroup()
 {
-   UT_DEBUGMSG(("WordPerfect: Handling a display number rerference group\n"));
+   UT_DEBUGMSG(("WordPerfect: Handling a display number reference group\n"));
    unsigned char subGroup, flags;
    long startPosition;
    UT_uint16 size;
 
    X_CheckWordPerfectError(_handleVariableGroupHeader(startPosition, subGroup, size, flags));
+   
+   switch (subGroup) 
+     {
+      case WP_DISPLAY_NUMBER_REFERENCE_GROUP_PARAGRAPH_NUMBER_DISPLAY_ON:
+	UT_DEBUGMSG(("WordPerfect: Display number reference group (about to display number)\n"));
+	if (m_paragraphStyleState == beginPart2Numbering)
+	  m_paragraphStyleState = beginPart2DisplayReferencing;
+	break;
+      case WP_DISPLAY_NUMBER_REFERENCE_GROUP_PARAGRAPH_NUMBER_DISPLAY_OFF:
+	UT_DEBUGMSG(("WordPerfect: Display number reference group (no longer displaying number)\n"));
+	if (m_paragraphStyleState == beginPart2DisplayReferencing)
+	  m_paragraphStyleState = beginPart2Numbering;
+	break;
+     }
+   
    X_CheckWordPerfectError(_skipGroup(startPosition, size));
    
    return UT_OK;
@@ -1116,6 +1330,8 @@
    return UT_OK;
 }
 
+// handles a merge group
+// (TODO: not implemented, just skips over it)
 UT_Error IE_Imp_WordPerfect::_handleMergeGroup()
 {
    UT_DEBUGMSG(("WordPerfect: Handling a merge group\n"));
@@ -1129,6 +1345,8 @@
    return UT_OK;
 }
 
+// handles a box group (which has something to do with wordperfect graphics)
+// (TODO: not really implemented, parses a bunch of info, but doesn't do anything with it)
 UT_Error IE_Imp_WordPerfect::_handleBoxGroup()
 {
    UT_DEBUGMSG(("WordPerfect: Handling a box group\n"));
@@ -1196,7 +1414,9 @@
    int readVal = fgetc(m_importFile); // TODO: handle case that we get eof?
    X_CheckFileError(readVal);
    
-   if(!m_undoOn)
+   if(!m_undoOn && m_paragraphStyleState != beginPart2BeforeNumbering && m_paragraphStyleState != beginPart2Numbering && 
+      m_paragraphStyleState != beginPart2DisplayReferencing && m_paragraphStyleState != beginPart2AfterNumbering && 
+      m_paragraphStyleState != end)
      {
 	// flush what's come before this change (even if it's nothing, which
 	// IS a case we have to be worried about in case we are writing the first
@@ -1232,7 +1452,9 @@
    int readVal = fgetc(m_importFile); // TODO: handle case that we get eof?
    X_CheckFileError(readVal);
    
-   if(!m_undoOn)
+   if(!m_undoOn && m_paragraphStyleState != beginPart2BeforeNumbering && m_paragraphStyleState != beginPart2Numbering && 
+      m_paragraphStyleState != beginPart2DisplayReferencing && m_paragraphStyleState != beginPart2AfterNumbering && 
+      m_paragraphStyleState != end)
      {
 	// flush what's come before this change (even if it's nothing, which
 	// IS a case we have to be worried about in case we are writing the first
@@ -1258,6 +1480,7 @@
    return UT_OK;
 }
 
+// handles a character group (related to stuff like font size changing and list recognition)
 UT_Error IE_Imp_WordPerfect::_handleCharacterGroup()
 {
    UT_DEBUGMSG(("WordPerfect: Handling a character group\n"));
@@ -1277,6 +1500,34 @@
       case WP_CHARACTER_GROUP_FONT_SIZE_CHANGE:
 	X_CheckWordPerfectError(_handleFontSizeChange());
 	break;
+      case WP_CHARACTER_GROUP_PARAGRAPH_NUMBER_ON:
+	if (m_paragraphStyleState == beginPart2BeforeNumbering)
+	  {
+	     m_bPutativeListHasParagraphNumber = true; // indicates that a paragraph style really does encapsulate a list
+	     UT_uint16 nonDeletableInfoSize;
+	     UT_uint16 outlineStyleHash;
+	     unsigned char flag;
+	     X_CheckFileReadElementError(fread(&nonDeletableInfoSize, sizeof(UT_uint16), 1, m_importFile));
+	     X_CheckFileReadElementError(fread(&m_currentOutlineHash, sizeof(UT_uint16), 1, m_importFile));
+	     X_CheckFileReadElementError(fread(&m_currentListLevel, sizeof(unsigned char), 1, m_importFile));
+	     X_CheckFileReadElementError(fread(&flag, sizeof(unsigned char), 1, m_importFile));
+	     UT_DEBUGMSG(("WordPerfect: LISTS Paragraph Number ON (outlineStyleHash: %i, level: %i, flag: %i)\n", (int)m_currentOutlineHash, (int)m_currentListLevel, (int) flag));
+	     // first, find the correct list definition
+	     WordPerfectListDefinition *listDefinition = _getListDefinition(m_currentOutlineHash);	     
+	     if( listDefinition == NULL )
+	       return UT_ERROR;	     
+	     X_CheckWordPerfectError(_updateDocumentListDefinition(listDefinition, m_currentListLevel));
+	     if (listDefinition->isLevelNumbered(m_currentListLevel))
+	       listDefinition->incrementLevelNumber(m_currentListLevel);
+	     m_currentListTag = UT_rand();
+	     m_paragraphStyleState = beginPart2Numbering;
+	  }	
+	break;
+      case WP_CHARACTER_GROUP_PARAGRAPH_NUMBER_OFF:
+	UT_DEBUGMSG(("WordPerfect: LISTS Paragraph Number OFF\n"));
+	if (m_paragraphStyleState == beginPart2Numbering || m_paragraphStyleState == beginPart2DisplayReferencing)
+	  m_paragraphStyleState = beginPart2AfterNumbering;
+	break;
       default:
 	break;
      }
@@ -1379,7 +1630,7 @@
    int characterSet = fgetc(m_importFile);
    X_CheckFileError(characterSet);
    
-   if(!m_undoOn)
+   if(!m_undoOn && m_paragraphStyleState != beginPart2BeforeNumbering && m_paragraphStyleState != beginPart2Numbering && m_paragraphStyleState != beginPart2AfterNumbering && m_paragraphStyleState !=end)
      {
 	// TODO: hack, hack, hack
 	// find out how to reliably map ALL characters between character sets and extended characters
@@ -1410,6 +1661,9 @@
    return UT_OK;
 }
 
+// handles a font face change
+// (supposedly, not really actually, we parse a bunch of information but don't do anything with it yet-- abi's font system
+// is too fucked at the moment to make it worth bothering with -WL)
 UT_Error IE_Imp_WordPerfect::_handleFontFaceChange()
 {
    UT_DEBUGMSG(("WordPerfect: Handling a Font Face Change\n"));
@@ -1433,13 +1687,15 @@
    UT_DEBUGMSG(("WordPerfect: Got this font face change info: (num PIDS: %i, font descriptor PID: %i, old matched point size: %i, hash: %i, matched font index: %i, matched font point size: %i)\n",
 		(int) numPIDs, (int) fontDescriptorPID, (int) oldMatchedPointSize, (int) hash, (int) matchedFontIndex, (int) matchedFontPointSize));
 
-   m_textAttributes.m_fontSize = (UT_uint16) rint((double)((((float)matchedFontPointSize)/100.0f)*2.0f)); // fixme: ghastly magic numbers;
+   m_textAttributes.m_fontSize = (UT_uint16) rint((double)((((float)matchedFontPointSize)/100.0f)*2.0f)); // fixme: ghastly magic numbers;   
    X_CheckWordPerfectError(_flushText());
    X_CheckWordPerfectError(_appendCurrentTextProperties());
 
    return UT_OK;
 }
 
+// handles a font size change
+// FIXME: we could be more precise about this..
 UT_Error IE_Imp_WordPerfect::_handleFontSizeChange()
 {
    UT_DEBUGMSG(("WordPerfect: Handling a Font Size Change\n"));
@@ -1470,10 +1726,12 @@
    return UT_OK;
 }
 
+// _handleUndo: handles a wordperfect undo group, which defines area of text which are "invalid"
+// we basically handle this by skipping over any text which wordperfect deems invalid
 UT_Error IE_Imp_WordPerfect::_handleUndo()
 {
-   // this function isn't very well documented and could very well be buggy
-   // it is based off of my interpretation of a single test file
+   // this function isn't very well documented 
+   // but this seems to work fine after repeated testing
    UT_DEBUGMSG(("WordPerfect: Handling an undo group\n"));
    long startPosition = ftell(m_importFile);
 
@@ -1496,42 +1754,90 @@
    return UT_OK;
 }
 
+// handles a paragraph justification (e.g.: manipulating how a paragraph is positioned)
 UT_Error IE_Imp_WordPerfect::_handleParagraphGroupJustification()
 {
    UT_DEBUGMSG(("WordPerfect: Handling a paragraph group's justification\n"));
  
+   UT_uint16 nonDeletableInfoSize; // we don't really care about this..
+   X_CheckFileReadElementError(fread(&nonDeletableInfoSize, sizeof(UT_uint16), 1, m_importFile));
+   
    unsigned char paragraphJustification;
    X_CheckFileReadElementError(fread(&paragraphJustification, sizeof(unsigned char), 1, m_importFile));
 
-   if(!m_undoOn)
-     {	
-	switch(paragraphJustification)
-	  {
-	   case WP_PARAGRAPH_GROUP_JUSTIFICATION_LEFT:
-	     m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::left;
-	     break;
-	   case WP_PARAGRAPH_GROUP_JUSTIFICATION_FULL:
-	     m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::full;
-	     break;
-	   case WP_PARAGRAPH_GROUP_JUSTIFICATION_CENTER:
-	     m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::center;
-	     break;
-	   case WP_PARAGRAPH_GROUP_JUSTIFICATION_RIGHT:
-	     m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::right;
-	     break;
-	   case WP_PARAGRAPH_GROUP_JUSTIFICATION_FULL_ALL_LINES:
-	     m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::fullAllLines;
-	     break;
-	   case WP_PARAGRAPH_GROUP_JUSTIFICATION_RESERVED:
-	     m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::reserved;
-	     break;
-	  }
-    	UT_DEBUGMSG(("WordPerfect: Paragraph Justification is now: %i\n", paragraphJustification));
+   switch(paragraphJustification)
+     {
+      case WP_PARAGRAPH_GROUP_JUSTIFICATION_LEFT:
+	m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::left;
+	break;
+      case WP_PARAGRAPH_GROUP_JUSTIFICATION_FULL:
+	m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::full;
+	break;
+      case WP_PARAGRAPH_GROUP_JUSTIFICATION_CENTER:
+	m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::center;
+	break;
+      case WP_PARAGRAPH_GROUP_JUSTIFICATION_RIGHT:
+	m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::right;
+	break;
+      case WP_PARAGRAPH_GROUP_JUSTIFICATION_FULL_ALL_LINES:
+	m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::fullAllLines;
+	break;
+      case WP_PARAGRAPH_GROUP_JUSTIFICATION_RESERVED:
+	m_paragraphProperties.m_justificationMode = WordPerfectParagraphProperties::reserved;
+	break;
      }
+   UT_DEBUGMSG(("WordPerfect: Paragraph Justification is now: %i\n", paragraphJustification));
    
    return UT_OK;
 }
 
+// _handleOutlineDefine: parses a WordPerfect outline definition, creates an importer-temporary list definition and stores it for later use
+// Outline Definitions are used to define "lists" in WordPerfect
+UT_Error IE_Imp_WordPerfect::_handleOutlineDefine()
+{
+   unsigned char numPrefixIDs;
+   UT_uint16 outlineStylePID;
+   UT_uint16 paragraphStylePIDs[WP_NUM_LIST_LEVELS]; // seemingly useless
+   UT_uint16 nonDeletableInfoSize;
+   UT_uint16 definitionHash;
+   UT_uint16 numberingMethods[WP_NUM_LIST_LEVELS];
+   unsigned char outlineFlags;
+   unsigned char tabBehaviourFlag;
+      
+   X_CheckFileReadElementError(fread(&numPrefixIDs, sizeof(unsigned char), 1, m_importFile));
+   X_CheckFileReadElementError(fread(&outlineStylePID, sizeof(UT_uint16), 1, m_importFile));
+   for (unsigned int i=0; i<WP_NUM_LIST_LEVELS; i++) 
+	X_CheckFileReadElementError(fread(&paragraphStylePIDs[i], sizeof(UT_uint16), 1, m_importFile));
+   X_CheckFileReadElementError(fread(&nonDeletableInfoSize, sizeof(UT_uint16), 1, m_importFile));
+   X_CheckFileReadElementError(fread(&definitionHash, sizeof(UT_uint16), 1, m_importFile)); // this is how we identify the list an element may belong to
+   for (unsigned int i=0; i<WP_NUM_LIST_LEVELS; i++) 
+	X_CheckFileReadElementError(fread(&numberingMethods[i], sizeof(UT_uint16), 1, m_importFile));
+   X_CheckFileReadElementError(fread(&outlineFlags, sizeof(unsigned char), 1, m_importFile));
+   X_CheckFileReadElementError(fread(&tabBehaviourFlag, sizeof(unsigned char), 1, m_importFile));
+   
+   UT_DEBUGMSG(("WordPerfect: Read Outline Define Group (numPrefixIDs: %i, outlineStylePID: %i, nonDeletableInfoSize: %i, definitionHash: %i, outlineFlags: %s, tabBehaviourFlag)\n", (int) numPrefixIDs, (int) outlineStylePID, (int) nonDeletableInfoSize, (int) definitionHash, (int) outlineFlags, (int) tabBehaviourFlag));
+   UT_DEBUGMSG(("WordPerfect: Read Outline Define Group (paragraphStylePIDs: %i %i %i %i %i %i %i %i)\n", paragraphStylePIDs[0], paragraphStylePIDs[1], paragraphStylePIDs[2], paragraphStylePIDs[3],
+		paragraphStylePIDs[4], paragraphStylePIDs[5], paragraphStylePIDs[6], paragraphStylePIDs[7]));
+   UT_DEBUGMSG(("WordPerfect: Read Outline Define Group (numberingMethods: %i %i %i %i %i %i %i %i)\n", numberingMethods[0], numberingMethods[1], numberingMethods[2], numberingMethods[3],
+		numberingMethods[4], numberingMethods[5], numberingMethods[6], numberingMethods[7]));
+   
+   // we're starting a new outline, so reset it, and put the more explicit properties offered by this group into the list definition
+   for (UT_uint32 i=0; i<m_listDefinitionList.size(); i++)
+     {
+	WordPerfectListDefinition *tempListDefinition = (WordPerfectListDefinition *) m_listDefinitionList.getNthItem( i );
+	if( tempListDefinition->getOutlineHash() == definitionHash )
+	  {
+	     tempListDefinition->resetListIDsAndNumbers();
+	     tempListDefinition->updateListTypes(numberingMethods);
+	     return UT_OK;
+	  }	
+     }
+   
+   // couldn't find the list definition matching the outline hash. this is scary, abort.
+   return UT_ERROR;
+}
+
+
 // _handleVariableGroupHeader: gets the info common to all groups
 UT_Error IE_Imp_WordPerfect::_handleVariableGroupHeader(long &startPosition, unsigned char &subGroup, UT_uint16 &size, unsigned char &flags)
 {
@@ -1559,14 +1865,23 @@
 UT_Error IE_Imp_WordPerfect::_flushText()
 {
    UT_DEBUGMSG(("WordPerfect: Flushing Text\n"));
-   	
+         
+   // place any deferred paragraph breaks in now
+   while (m_numDeferredParagraphBreaks > 0)
+     {
+	UT_DEBUGMSG(("WordPerfect: Placing in a deferred paragraph break\n"));
+	_appendCurrentParagraphProperties();
+	m_numDeferredParagraphBreaks--;
+     }
+   
    // append the current paragraph properties, but only when the paragraph properties 
-   // have changed or there is no paragraph at all
+   // have changed or there is no paragraph at all (and there is text to flush)
    if(m_bParagraphChanged || (!m_bParagraphExists))
      {	
+	UT_DEBUGMSG(("WordPerfect: Appending Paragraph Properties\n"));
 	_appendCurrentParagraphProperties();
      }
-   
+         
    if(m_textBuf.getLength() > 0)
      X_CheckDocumentError(getDoc()->appendSpan((UT_UCSChar *)m_textBuf.getPointer(0), m_textBuf.getLength()));   
    m_textBuf.truncate(0);
@@ -1575,10 +1890,102 @@
    return UT_OK;
 }
 
+// insert the text in the current textbuf to the document, taking its
+// style into account
+UT_Error IE_Imp_WordPerfect::_appendCurrentListProperties()
+{
+   UT_DEBUGMSG(("WordPerfect: Appending Current List Properties (outline hash: %i)\n", m_currentOutlineHash));
+
+   WordPerfectListDefinition *listDefinition = _getListDefinition(m_currentOutlineHash);
+   if (listDefinition == NULL)
+     return UT_ERROR;
+   
+   UT_String szListID;
+   UT_String szParentID;
+   UT_String szLevel;
+   UT_String_sprintf(szListID,"%d",listDefinition->getListID(m_currentListLevel));
+   if (m_currentListLevel > 0) 
+     UT_String_sprintf(szParentID,"%d", listDefinition->getListID((m_currentListLevel-1)));
+   else
+     UT_String_sprintf(szParentID,"0"); 
+   UT_String_sprintf(szLevel,"%d", (m_currentListLevel+1));
+
+   const XML_Char* listAttribs[PT_MAX_ATTRIBUTES*2 + 1];
+   UT_uint32 attribsCount=0;
+   
+   listAttribs[attribsCount++] = PT_LISTID_ATTRIBUTE_NAME;
+   listAttribs[attribsCount++] = szListID.c_str();
+   listAttribs[attribsCount++] = PT_PARENTID_ATTRIBUTE_NAME;
+   listAttribs[attribsCount++] = szParentID.c_str();
+   listAttribs[attribsCount++] = PT_LEVEL_ATTRIBUTE_NAME;
+   listAttribs[attribsCount++] = szLevel.c_str();
+
+   // Now handle the Abi List properties
+   UT_String propBuffer;
+   UT_String tempBuffer;
+   UT_String_sprintf(tempBuffer,"list-style:%d;", listDefinition->getListType(m_currentListLevel));
+   propBuffer += tempBuffer;
+   // FIXME: writing the list delimiter is kind of tricky and silly (because wordperfect wants to define
+   // it within the document, while abi wants to (sensibly probably) define it in the list definition)
+   // (we reset it each time but only for numbered lists)
+   if (listDefinition->isLevelNumbered(m_currentListLevel)) 
+     {	
+	UT_DEBUGMSG(("WordPerfect: Appending this list delim: %s\n", m_rightListDelim.c_str()));
+	listDefinition->setListRightDelimText(m_currentListLevel, m_rightListDelim.c_str());
+	X_CheckWordPerfectError(_updateDocumentListDefinition(listDefinition, m_currentListLevel));
+     }   
+   if (listDefinition->getListType(m_currentListLevel) == BULLETED_LIST)
+     UT_String_sprintf(tempBuffer, "field-font:Symbol; ");
+   else
+     UT_String_sprintf(tempBuffer, "field-font:NULL; ");
+   propBuffer += tempBuffer;
+   UT_String_sprintf(tempBuffer, "start-value:%i; ", listDefinition->getListNumber(m_currentListLevel));
+   propBuffer += tempBuffer;
+   UT_String_sprintf(tempBuffer, "text-indent:%fin; ", m_paragraphStyleTextIndent); 
+   propBuffer += tempBuffer;
+   UT_String_sprintf(tempBuffer, "margin-left:%fin", m_paragraphStyleMarginLeft);
+   propBuffer += tempBuffer;
+   listAttribs[attribsCount++] = PT_PROPS_ATTRIBUTE_NAME;
+   listAttribs[attribsCount++] = propBuffer.c_str();
+   listAttribs[attribsCount++] = NULL;
+
+   if ( (!m_bInSection) || m_bSectionChanged)
+     X_CheckWordPerfectError(_appendSection ());
+
+   X_CheckDocumentError(getDoc()->appendStrux(PTX_Block, listAttribs));   
+
+   UT_DEBUGMSG(("WordPerfect: LISTS - Appended a list attributes section (text-indent: %f, margin-left:%f)\n", m_paragraphStyleTextIndent, m_paragraphStyleMarginLeft));
+
+   // hang text off of a list label
+   X_CheckWordPerfectError(_appendCurrentTextProperties());
+   getDoc()->appendFmtMark();
+   m_currentListTag = 0;
+   UT_DEBUGMSG(("WordPerfect: LISTS - Appended a list tag def'n (character props)\n"));
+   
+   // append a list field label
+   const XML_Char* fielddef[3];
+   fielddef[0] ="type";
+   fielddef[1] = "list_label";
+   fielddef[2] = NULL;
+   X_CheckDocumentError(getDoc()->appendObject(PTO_Field,fielddef));
+   UT_DEBUGMSG(("WordPerfect: LISTS - Appended a field def'n\n"));
+      
+   //X_CheckWordPerfectError(_appendCurrentTextProperties());
+   X_CheckWordPerfectError(_appendCurrentTextProperties());
+   
+   m_bParagraphExists = true; // in case we start the document with a list
+   m_bParagraphChanged = false; // we already changed the paragraph here, so don't go around saying it hasn't been changed when we flush the text
+   
+   //m_leftListDelim.clear();
+   m_rightListDelim.clear();
+   
+   return UT_OK;
+}
+
 UT_Error IE_Imp_WordPerfect::_appendCurrentTextProperties()
 {
    UT_DEBUGMSG(("WordPerfect: Appending current text properties\n"));
-   
+      
    XML_Char* pProps = "props";
    UT_String propBuffer;
    UT_String tempBuffer;
@@ -1620,12 +2027,26 @@
    UT_String_sprintf(tempBuffer, "; font-size:%spt", std_size_string((float)m_textAttributes.m_fontSize));
    propBuffer += tempBuffer;
    
+   if(m_currentListTag != 0)
+     {
+	// List Tag to hang lists off
+	UT_String_sprintf(tempBuffer, "; list-tag:%d", m_currentListTag);
+	propBuffer += tempBuffer;
+     }
+   
    UT_DEBUGMSG(("Appending Format: %s\n", propBuffer.c_str()));
-   const XML_Char* propsArray[3];
+   const XML_Char* propsArray[5];
+
    propsArray[0] = pProps;
    propsArray[1] = propBuffer.c_str();
    propsArray[2] = NULL;
-   
+   if (m_bPutativeListHasParagraphNumber) 
+     {
+	propsArray[2] ="type";
+	propsArray[3] = "list_label";
+	propsArray[4] = NULL;
+     }	
+
    X_CheckDocumentError(getDoc()->appendFmt(propsArray));
 
    return UT_OK;
@@ -1725,5 +2146,60 @@
    m_bInSection = true;
    m_bSectionChanged = false;
    m_bParagraphInSection = false;
+   return UT_OK;
+}
+
+WordPerfectListDefinition * IE_Imp_WordPerfect::_getListDefinition(UT_uint16 outlineHash)
+{
+  for (UT_uint32 i=0; i<m_listDefinitionList.size(); i++)
+     {
+	WordPerfectListDefinition *tempListDefinition = (WordPerfectListDefinition *) m_listDefinitionList.getNthItem( i );
+	if( tempListDefinition->getOutlineHash() == outlineHash )
+	  {
+	     return tempListDefinition;
+	  }
+     }
+   
+   return NULL;	
+}
+
+UT_Error IE_Imp_WordPerfect::_updateDocumentListDefinition(WordPerfectListDefinition *listDefinition, int level)
+{
+   // add a list definition to the current document, if necessary
+   if (listDefinition->getListID(level) == 0)
+     listDefinition->setListID(level, UT_rand());
+	     
+   // finally, set the document's list identification info..
+   // FIXME: AbiWord doesn't support different types of lists being appended to their parents.. so we just have to stick with what level 0 provides
+   int startingNumber;
+   if (listDefinition->getListType(0) == BULLETED_LIST) // REPLACE WITH (WHEN FIXED IN ABI): if (listDefinition->getListType(level) == BULLETED_LIST)
+     startingNumber = 0;
+   else
+     startingNumber = 1;
+   fl_AutoNum * pAuto = getDoc()->getListByID(listDefinition->getListID(level));
+   // not in document yet, we should create a list for it
+   if (pAuto == NULL) 
+     {	
+	if (level > 0) 
+	  {	
+	     // REPLACE WITH (WHEN FIXED IN ABI): pAuto = new fl_AutoNum(listDefinition->getListID(level), listDefinition->getListID((level-1)), listDefinition->getListType(level), startingNumber, (XML_Char *)"%L", ".", getDoc());
+	     pAuto = new fl_AutoNum(listDefinition->getListID(level), listDefinition->getListID((level-1)), listDefinition->getListType(0), startingNumber, (XML_Char *)listDefinition->getListDelim(level).c_str(), ".", getDoc());
+	  }   
+	else
+	  pAuto = new fl_AutoNum(listDefinition->getListID(level), 0, listDefinition->getListType(level), startingNumber, (XML_Char *)listDefinition->getListDelim(level).c_str(), ".", getDoc());
+	
+	getDoc()->addList(pAuto);
+     }
+   // we should update what we have
+   else 
+     {
+	
+	// ADD (WHEN FIXED IN ABI): pAuto->setListType(listDefinition->getListType(level));
+	pAuto->setStartValue(startingNumber);
+	pAuto->setDelim((XML_Char *)listDefinition->getListDelim(level).c_str());
+     }
+   
+   pAuto->fixHierarchy();
+   
    return UT_OK;
 }

Reply via email to