/*
 * RichEdit - functions dealing with editor object
 *
 * 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);

void ME_EmptyUndoStack(ME_TextEditor *editor)
{
  ME_DisplayItem *p, *pNext;
  
  if (editor->nUndoMode == umIgnore)
    return;
  
  TRACE("Emptying undo stack\n");

  p = editor->pUndoStack;
  editor->pUndoStack = editor->pUndoStackBottom = NULL;
  editor->nUndoStackSize = 0;
  while(p) {
    pNext = p->next;
    ME_DestroyDisplayItem(p);    
    p = pNext;
  } 
  p = editor->pRedoStack;
  editor->pRedoStack = NULL;
  while(p) {
    pNext = p->next;
    ME_DestroyDisplayItem(p);    
    p = pNext;
  } 
}

ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_DisplayItem *pdi) {
  if (editor->nUndoMode == umIgnore)
    return NULL;
  else if (editor->nUndoLimit == 0)
    return NULL;
  else
  {
    ME_DisplayItem *pItem = ALLOC_OBJ(ME_UndoItem);
    switch(type)
    {
    case diUndoPotentialEndTransaction:
        /* only should be added for manually typed chars, not undos or redos */
        assert(editor->nUndoMode == umAddToUndo);
        /* intentional fall-through to next case */
    case diUndoEndTransaction:
      break;
    case diUndoSetParagraphFormat:
      assert(pdi);
      pItem->member.para = pdi->member.para;
      pItem->member.para.pFmt = ALLOC_OBJ(PARAFORMAT2);
      *pItem->member.para.pFmt = *pdi->member.para.pFmt;
      break;
    case diUndoInsertRun:
      assert(pdi);
      pItem->member.run = pdi->member.run;
      pItem->member.run.strText = ME_StrDup(pItem->member.run.strText);
      ME_AddRefStyle(pItem->member.run.style);
      if (pdi->member.run.ole_obj)
      {
        pItem->member.run.ole_obj = ALLOC_OBJ(*pItem->member.run.ole_obj);
        ME_CopyReObject(pItem->member.run.ole_obj, pdi->member.run.ole_obj);
      }
      else pItem->member.run.ole_obj = NULL;
      break;
    case diUndoSetCharFormat:
      break;
    case diUndoDeleteRun:
    case diUndoJoinParagraphs:
      break;
    case diUndoSplitParagraph:
    {
      ME_DisplayItem *prev_para = pdi->member.para.prev_para;
      assert(pdi->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
      pItem->member.para.pFmt = ALLOC_OBJ(PARAFORMAT2);
      pItem->member.para.pFmt->cbSize = sizeof(PARAFORMAT2);
      pItem->member.para.pFmt->dwMask = 0;
      *pItem->member.para.pFmt = *pdi->member.para.pFmt;
      pItem->member.para.border = pdi->member.para.border;
      pItem->member.para.nFlags = prev_para->member.para.nFlags & ~MEPF_CELL;
      pItem->member.para.pCell = NULL;
      break;
    }
    default:
      assert(0 == "AddUndoItem, unsupported item type");
      return NULL;
    }
    pItem->type = type;
    pItem->prev = NULL;
    if (editor->nUndoMode == umAddToUndo || editor->nUndoMode == umAddBackToUndo)
    {
      if (editor->pUndoStack
          && editor->pUndoStack->type == diUndoPotentialEndTransaction)
      {
          editor->pUndoStack->type = diUndoEndTransaction;
      }
      if (editor->nUndoMode == umAddToUndo)
        TRACE("Pushing id=%s to undo stack, deleting redo stack\n", ME_GetDITypeName(type));
      else
        TRACE("Pushing id=%s to undo stack\n", ME_GetDITypeName(type));

      pItem->next = editor->pUndoStack;
      if (type == diUndoEndTransaction || type == diUndoPotentialEndTransaction)
        editor->nUndoStackSize++;
      if (editor->pUndoStack)
        editor->pUndoStack->prev = pItem;
      else
        editor->pUndoStackBottom = pItem;
      editor->pUndoStack = pItem;
      
      if (editor->nUndoStackSize > editor->nUndoLimit)
      { /* remove oldest undo from stack */
        ME_DisplayItem *p = editor->pUndoStackBottom;
        while (p->type !=diUndoEndTransaction)
          p = p->prev; /*find new stack bottom */
        editor->pUndoStackBottom = p->prev;
          editor->pUndoStackBottom->next = NULL;
        do
        {
          ME_DisplayItem *pp = p->next;
          ME_DestroyDisplayItem(p);
          p = pp;
        } while (p);
        editor->nUndoStackSize--;
      }
      /* any new operation (not redo) clears the redo stack */
      if (editor->nUndoMode == umAddToUndo) {
        ME_DisplayItem *p = editor->pRedoStack;
        while(p)
        {
          ME_DisplayItem *pp = p->next;
          ME_DestroyDisplayItem(p);
          p = pp;
        }
        editor->pRedoStack = NULL;
      }
    }
    else if (editor->nUndoMode == umAddToRedo)
    {
      TRACE("Pushing id=%s to redo stack\n", ME_GetDITypeName(type));
      pItem->next = editor->pRedoStack;
      if (editor->pRedoStack)
        editor->pRedoStack->prev = pItem;
      editor->pRedoStack = pItem;
    }
    else
      assert(0);
    return (ME_UndoItem *)pItem;
  }
}

/**
 * Commits preceding changes into a transaction that can be undone together.
 *
 * This should be called after all the changes occur associated with an event
 * so that the group of changes can be undone atomically as a transaction.
 *
 * This will have no effect the undo mode is set to ignore changes, or if no
 * changes preceded calling this function before the last time it was called.
 *
 * This can also be used to conclude a coalescing transaction (used for grouping
 * typed characters).
 */
void ME_CommitUndo(ME_TextEditor *editor) {
  if (editor->nUndoMode == umIgnore)
    return;
  
  assert(editor->nUndoMode == umAddToUndo);
  
  /* no transactions, no need to commit */
  if (!editor->pUndoStack)
    return;

  /* no need to commit empty transactions */
  if (editor->pUndoStack->type == diUndoEndTransaction)
    return;
    
  if (editor->pUndoStack->type == diUndoPotentialEndTransaction)
  {
      /* Previous transaction was as a result of characters typed,
       * so the end of this transaction is confirmed. */
      editor->pUndoStack->type = diUndoEndTransaction;
      return;
  }

  ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
}

/**
 * Groups supsequent changes with previous ones for an undo if coalescing.
 *
 * Has no effect if the previous changes were followed by a ME_CommitUndo. This
 * function will only have an affect if the previous changes were followed by
 * a call to ME_CommitCoalescingUndo, which allows the transaction to be
 * continued.
 *
 * This allows multiple consecutively typed characters to be grouped together
 * to be undone by a single undo operation.
 */
void ME_ContinueCoalescingTransaction(ME_TextEditor *editor)
{
  ME_DisplayItem* p;

  if (editor->nUndoMode == umIgnore)
    return;

  assert(editor->nUndoMode == umAddToUndo);

  p = editor->pUndoStack;

  if (p && p->type == diUndoPotentialEndTransaction) {
    assert(p->next); /* EndTransactions shouldn't be at bottom of undo stack */
    editor->pUndoStack = p->next;
    editor->pUndoStack->prev = NULL;
    editor->nUndoStackSize--;
    ME_DestroyDisplayItem(p);
  }
}

/**
 * Commits preceding changes into a undo transaction that can be expanded.
 *
 * This function allows the transaction to be reopened with
 * ME_ContinueCoalescingTransaction in order to continue the transaction.  If an
 * undo item is added to the undo stack as a result of a change without the
 * transaction being reopened, then the transaction will be ended, and the
 * changes will become a part of the next transaction.
 *
 * This is used to allow typed characters to be grouped together since each
 * typed character results in a single event, and each event adding undo items
 * must be committed.  Using this function as opposed to ME_CommitUndo allows
 * multiple events to be grouped, and undone together.
 */
void ME_CommitCoalescingUndo(ME_TextEditor *editor)
{
  if (editor->nUndoMode == umIgnore)
    return;

  assert(editor->nUndoMode == umAddToUndo);

  /* no transactions, no need to commit */
  if (!editor->pUndoStack)
    return;

  /* no need to commit empty transactions */
  if (editor->pUndoStack->type == diUndoEndTransaction)
    return;
  if (editor->pUndoStack->type == diUndoPotentialEndTransaction)
    return;

  ME_AddUndoItem(editor, diUndoPotentialEndTransaction, NULL);
}

static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
{
  ME_UndoItem *pUItem = (ME_UndoItem *)pItem;

  if (editor->nUndoMode == umIgnore)
    return;
  TRACE("Playing undo/redo item, id=%s\n", ME_GetDITypeName(pItem->type));

  switch(pItem->type)
  {
  case diUndoPotentialEndTransaction:
  case diUndoEndTransaction:
    assert(0);
  case diUndoSetParagraphFormat:
  {
    ME_Cursor tmp;
    ME_DisplayItem *para;
    ME_CursorFromCharOfs(editor, pItem->member.para.nCharOfs, &tmp);
    para = ME_FindItemBack(tmp.pRun, diParagraph);
    ME_AddUndoItem(editor, diUndoSetParagraphFormat, para);
    *para->member.para.pFmt = *pItem->member.para.pFmt;
    para->member.para.border = pItem->member.para.border;
    break;
  }
  case diUndoSetCharFormat:
  {
    ME_Cursor start, end;
    ME_CursorFromCharOfs(editor, pUItem->nStart, &start);
    end = start;
    ME_MoveCursorChars(editor, &end, pUItem->nLen);
    ME_SetCharFormat(editor, &start, &end, &pItem->member.ustyle->fmt);
    break;
  }
  case diUndoInsertRun:
  {
    ME_Cursor tmp;
    ME_CursorFromCharOfs(editor, pItem->member.run.nCharOfs, &tmp);
    ME_InsertRunAtCursor(editor, &tmp, pItem->member.run.style,
                         pItem->member.run.strText->szData,
                         pItem->member.run.strText->nLen,
                         pItem->member.run.nFlags);
    break;
  }
  case diUndoDeleteRun:
  {
    ME_Cursor tmp;
    ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
    ME_InternalDeleteText(editor, &tmp, pUItem->nLen, TRUE);
    break;
  }
  case diUndoJoinParagraphs:
  {
    ME_Cursor tmp;
    ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
    /* the only thing that's needed is paragraph offset, so no need to split runs */
    ME_JoinParagraphs(editor, tmp.pPara, TRUE);
    break;
  }
  case diUndoSplitParagraph:
  {
    ME_Cursor tmp;
    ME_DisplayItem *this_para, *new_para;
    BOOL bFixRowStart;
    int paraFlags = pItem->member.para.nFlags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND);
    ME_CursorFromCharOfs(editor, pUItem->nStart, &tmp);
    if (tmp.nOffset)
      tmp.pRun = ME_SplitRunSimple(editor, tmp.pRun, tmp.nOffset);
    assert(pUItem->eol_str);
    this_para = tmp.pPara;
    bFixRowStart = this_para->member.para.nFlags & MEPF_ROWSTART;
    if (bFixRowStart)
    {
      /* Re-insert the paragraph before the table, making sure the nFlag value
       * is correct. */
      this_para->member.para.nFlags &= ~MEPF_ROWSTART;
    }
    new_para = ME_SplitParagraph(editor, tmp.pRun, tmp.pRun->member.run.style,
                                 pUItem->eol_str, paraFlags);
    if (bFixRowStart)
      new_para->member.para.nFlags |= MEPF_ROWSTART;
    assert(pItem->member.para.pFmt->cbSize == sizeof(PARAFORMAT2));
    *new_para->member.para.pFmt = *pItem->member.para.pFmt;
    new_para->member.para.border = pItem->member.para.border;
    if (pItem->member.para.pCell)
    {
      ME_DisplayItem *pItemCell, *pCell;
      pItemCell = pItem->member.para.pCell;
      pCell = new_para->member.para.pCell;
      pCell->member.cell.nRightBoundary = pItemCell->member.cell.nRightBoundary;
      pCell->member.cell.border = pItemCell->member.cell.border;
    }
    break;
  }
  default:
    assert(0 == "PlayUndoItem, unexpected type");
  }
}

BOOL ME_Undo(ME_TextEditor *editor) {
  ME_DisplayItem *p;
  ME_UndoMode nMode = editor->nUndoMode;
  
  if (editor->nUndoMode == umIgnore)
    return FALSE;
  assert(nMode == umAddToUndo || nMode == umIgnore);
  
  /* no undo items ? */
  if (!editor->pUndoStack)
    return FALSE;
    
  /* watch out for uncommitted transactions ! */
  assert(editor->pUndoStack->type == diUndoEndTransaction
        || editor->pUndoStack->type == diUndoPotentialEndTransaction);
  
  editor->nUndoMode = umAddToRedo;
  p = editor->pUndoStack->next;
  ME_DestroyDisplayItem(editor->pUndoStack);
  editor->pUndoStack = p;
  do {
    p->prev = NULL;
    ME_PlayUndoItem(editor, p);
    editor->pUndoStack = p->next;
    ME_DestroyDisplayItem(p);
    p = editor->pUndoStack;
  } while(p && p->type != diUndoEndTransaction);
  if (p)
    p->prev = NULL;
  ME_MoveCursorFromTableRowStartParagraph(editor);
  ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
  ME_CheckTablesForCorruption(editor);
  editor->nUndoStackSize--;
  editor->nUndoMode = nMode;
  ME_UpdateRepaint(editor);
  return TRUE;
}

BOOL ME_Redo(ME_TextEditor *editor) {
  ME_DisplayItem *p;
  ME_UndoMode nMode = editor->nUndoMode;
  
  assert(nMode == umAddToUndo || nMode == umIgnore);
  
  if (editor->nUndoMode == umIgnore)
    return FALSE;
  /* no redo items ? */
  if (!editor->pRedoStack)
    return FALSE;
    
  /* watch out for uncommitted transactions ! */
  assert(editor->pRedoStack->type == diUndoEndTransaction);
  
  editor->nUndoMode = umAddBackToUndo;
  p = editor->pRedoStack->next;
  ME_DestroyDisplayItem(editor->pRedoStack);
  editor->pRedoStack = p;
  do {
    p->prev = NULL;
    ME_PlayUndoItem(editor, p);
    editor->pRedoStack = p->next;
    ME_DestroyDisplayItem(p);
    p = editor->pRedoStack;
  } while(p && p->type != diUndoEndTransaction);
  if (p)
    p->prev = NULL;
  ME_MoveCursorFromTableRowStartParagraph(editor);
  ME_AddUndoItem(editor, diUndoEndTransaction, NULL);
  ME_CheckTablesForCorruption(editor);
  editor->nUndoMode = nMode;
  ME_UpdateRepaint(editor);
  return TRUE;
}
