/*
 * 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 = (ME_DisplayItem *)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);
  ME_SendSelChange(editor);
}

/**
 * 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);
  ME_SendSelChange(editor);
}

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_SetCharFormat(editor, pUItem->nStart, pUItem->nLen, &pItem->member.ustyle->fmt);
    break;
  }
  case diUndoInsertRun:
  {
    ME_InsertRun(editor, pItem->member.run.nCharOfs, pItem);
    break;
  }
  case diUndoDeleteRun:
  {
    ME_InternalDeleteText(editor, pUItem->nStart, 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, ME_GetParagraph(tmp.pRun), 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 = ME_GetParagraph(tmp.pRun);
    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;
}
