/*
 * RichEdit - Basic operations on double linked lists.
 *
 * Copyright 2004 by Krzysztof Foltman
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */


#include "editor.h"

WINE_DEFAULT_DEBUG_CHANNEL(richedit_lists);

void ME_InsertBefore(ME_DisplayItem *diWhere, ME_DisplayItem *diWhat)
{
  diWhat->next = diWhere;
  diWhat->prev = diWhere->prev;

  diWhere->prev->next = diWhat;
  diWhat->next->prev = diWhat;
}

void ME_Remove(ME_DisplayItem *diWhere)
{
  ME_DisplayItem *diNext = diWhere->next;
  ME_DisplayItem *diPrev = diWhere->prev;
  assert(diNext);
  assert(diPrev);
  diPrev->next = diNext;
  diNext->prev = diPrev;
}

static BOOL ME_DITypesEqual(ME_DIType type, ME_DIType nTypeOrClass)
{
  switch (nTypeOrClass)
  {
    case diRunOrParagraph:
      return type == diRun || type == diParagraph;
    case diRunOrStartRow:
      return type == diRun || type == diStartRow;
    case diParagraphOrEnd:
      return type == diTextEnd || type == diParagraph;
    case diStartRowOrParagraph:
      return type == diStartRow || type == diParagraph;
    case diStartRowOrParagraphOrEnd:
      return type == diStartRow || type == diParagraph || type == diTextEnd;
    case diRunOrParagraphOrEnd:
      return type == diRun || type == diParagraph || type == diTextEnd;
    default:
      return type == nTypeOrClass;
  }
}

/* Modifies run pointer to point to the next run, and modify the
 * paragraph pointer if moving into the next paragraph.
 *
 * Returns TRUE if next run is found, otherwise returns FALSE. */
BOOL ME_NextRun(ME_DisplayItem **para, ME_DisplayItem **run)
{
  ME_DisplayItem *p = (*run)->next;
  while (p->type != diTextEnd)
  {
    if (p->type == diParagraph) {
      *para = p;
    } else if (p->type == diRun) {
      *run = p;
      return TRUE;
    }
    p = p->next;
  }
  return FALSE;
}

/* Modifies run pointer to point to the previous run, and modify the
 * paragraph pointer if moving into the previous paragraph.
 *
 * Returns TRUE if previous run is found, otherwise returns FALSE. */
BOOL ME_PrevRun(ME_DisplayItem **para, ME_DisplayItem **run)
{
  ME_DisplayItem *p = (*run)->prev;
  while (p->type != diTextStart)
  {
    if (p->type == diParagraph) {
      if (p->member.para.prev_para->type == diParagraph)
        *para = p->member.para.prev_para;
    } else if (p->type == diRun) {
      *run = p;
      return TRUE;
    }
    p = p->prev;
  }
  return FALSE;
}

ME_DisplayItem *ME_FindItemBack(ME_DisplayItem *di, ME_DIType nTypeOrClass)
{
  if (!di)
    return NULL;
  di = di->prev;
  while(di!=NULL) {
    if (ME_DITypesEqual(di->type, nTypeOrClass))
      return di;
    di = di->prev;
  }
  return NULL;
}

ME_DisplayItem *ME_FindItemBackOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass)
{
  while(di!=NULL) {
    if (ME_DITypesEqual(di->type, nTypeOrClass))
      return di;
    di = di->prev;
  }
  return NULL;
}

ME_DisplayItem *ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass)
{
  if (!di) return NULL;
  di = di->next;
  while(di!=NULL) {
    if (ME_DITypesEqual(di->type, nTypeOrClass))
      return di;
    di = di->next;
  }
  return NULL;
}

void ME_DestroyDisplayItem(ME_DisplayItem *item) {
/*  TRACE("type=%s\n", ME_GetDITypeName(item->type)); */
  if (item->type==diParagraph || item->type == diUndoSetParagraphFormat) {
    FREE_OBJ(item->member.para.pFmt);
  }
  if (item->type==diRun || item->type == diUndoInsertRun) {
    if (item->member.run.ole_obj) ME_DeleteReObject(item->member.run.ole_obj);
    ME_ReleaseStyle(item->member.run.style);
    ME_DestroyString(item->member.run.strText);
  }
  if (item->type==diUndoSetCharFormat) {
    ME_ReleaseStyle(item->member.ustyle);
  }
  if (item->type==diUndoSplitParagraph) {
     FREE_OBJ(item->member.para.pFmt);
     FREE_OBJ(item->member.para.pCell);
  }
  FREE_OBJ(item);
}

ME_DisplayItem *ME_MakeDI(ME_DIType type) {
  ME_DisplayItem *item = ALLOC_OBJ(ME_DisplayItem);
  ZeroMemory(item, sizeof(ME_DisplayItem));
  item->type = type;
  item->prev = item->next = NULL;
  if (type == diParagraph || type == diUndoSplitParagraph) {
    item->member.para.pFmt = ALLOC_OBJ(PARAFORMAT2);
    ME_SetDefaultParaFormat(item->member.para.pFmt);
    item->member.para.nFlags = MEPF_REWRAP;
  }
    
  return item;
}

const char *ME_GetDITypeName(ME_DIType type)
{
  switch(type)
  {
    case diParagraph: return "diParagraph";
    case diRun: return "diRun";
    case diCell: return "diCell";
    case diTextStart: return "diTextStart";
    case diTextEnd: return "diTextEnd";
    case diStartRow: return "diStartRow";
    case diUndoEndTransaction: return "diUndoEndTransaction";
    case diUndoPotentialEndTransaction: return "diUndoPotentialEndTransaction";
    case diUndoSetParagraphFormat: return "diUndoSetParagraphFormat";
    case diUndoSetCharFormat: return "diUndoSetCharFormat";
    case diUndoInsertRun: return "diUndoInsertRun";
    case diUndoDeleteRun: return "diUndoDeleteRun";
    case diUndoJoinParagraphs: return "diJoinParagraphs";
    case diUndoSplitParagraph: return "diSplitParagraph";
    default: return "?";
  }
}

void ME_DumpDocument(ME_TextBuffer *buffer)
{
  /* FIXME this is useless, */
  ME_DisplayItem *pItem = buffer->pFirst;
  TRACE("DOCUMENT DUMP START\n");
  while(pItem) {
    switch(pItem->type)
    {
      case diTextStart:
        TRACE("Start\n");
        break;
      case diCell:
        TRACE("Cell(level=%d%s)\n", pItem->member.cell.nNestingLevel,
              !pItem->member.cell.next_cell ? ", END" :
                (!pItem->member.cell.prev_cell ? ", START" :""));
        break;
      case diParagraph:
        TRACE("Paragraph(ofs=%d)\n", pItem->member.para.nCharOfs);
        if (pItem->member.para.nFlags & MEPF_ROWSTART)
          TRACE(" - (Table Row Start)\n");
        if (pItem->member.para.nFlags & MEPF_ROWEND)
          TRACE(" - (Table Row End)\n");
        break;
      case diStartRow:
        TRACE(" - StartRow\n");
        break;
      case diRun:
        TRACE(" - Run(\"%s\", %d, flags=%x)\n", debugstr_w(pItem->member.run.strText->szData),
          pItem->member.run.nCharOfs, pItem->member.run.nFlags);
        break;
      case diTextEnd:
        TRACE("End(ofs=%d)\n", pItem->member.para.nCharOfs);
        break;
      default:
        break;
    }
    pItem = pItem->next;
  }
  TRACE("DOCUMENT DUMP END\n");
}
