/****************************************************************************** * ME_MakeRun * * A helper function to create run structures quickly. */ ME_DisplayItem *ME_MakeRun(ME_Style *s, int nFlags) { ME_DisplayItem *item = ME_MakeDI(diRun); item->member.run.style = s; item->member.run.ole_obj = NULL; item->member.run.nFlags = nFlags; item->member.run.nCharOfs = -1; item->member.run.len = 0; item->member.run.para = NULL; ME_AddRefStyle(s); return item; }
ME_Style *ME_GetInsertStyle(ME_TextEditor *editor, int nCursor) { if (ME_IsSelection(editor)) { ME_Cursor c; int from, to; ME_GetSelection(editor, &from, &to); ME_CursorFromCharOfs(editor, from, &c); ME_AddRefStyle(c.pRun->member.run.style); return c.pRun->member.run.style; } if (editor->pBuffer->pCharStyle) { ME_AddRefStyle(editor->pBuffer->pCharStyle); return editor->pBuffer->pCharStyle; } else { ME_Cursor *pCursor = &editor->pCursors[nCursor]; ME_DisplayItem *pRunItem = pCursor->pRun; ME_DisplayItem *pPrevItem = NULL; if (pCursor->nOffset) { ME_Run *pRun = &pRunItem->member.run; ME_AddRefStyle(pRun->style); return pRun->style; } pPrevItem = ME_FindItemBack(pRunItem, diRunOrParagraph); if (pPrevItem->type == diRun) { ME_AddRefStyle(pPrevItem->member.run.style); return pPrevItem->member.run.style; } else { ME_AddRefStyle(pRunItem->member.run.style); return pRunItem->member.run.style; } } }
ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor) { ME_Style *style; int from, to; ME_GetSelection(editor, &from, &to); if (from != to) { ME_Cursor c; ME_CursorFromCharOfs(editor, from, &c); style = c.pRun->member.run.style; ME_AddRefStyle(style); /* ME_GetInsertStyle has already done that */ } else style = ME_GetInsertStyle(editor, 0); return style; }
/****************************************************************************** * ME_MakeRun * * A helper function to create run structures quickly. */ ME_DisplayItem *ME_MakeRun(ME_Style *s, int nFlags) { ME_DisplayItem *item = ME_MakeDI(diRun); item->member.run.style = s; item->member.run.ole_obj = NULL; item->member.run.nFlags = nFlags; item->member.run.nCharOfs = -1; item->member.run.len = 0; item->member.run.para = NULL; item->member.run.num_glyphs = 0; item->member.run.max_glyphs = 0; item->member.run.glyphs = NULL; item->member.run.vis_attrs = NULL; item->member.run.advances = NULL; item->member.run.offsets = NULL; item->member.run.max_clusters = 0; item->member.run.clusters = NULL; ME_AddRefStyle(s); return item; }
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); ((ME_UndoItem *)pItem)->nCR = ((ME_UndoItem *)pItem)->nLF = -1; 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; } }
ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, 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 diUndoEndTransaction: break; case diUndoSetParagraphFormat: assert(pdi); CopyMemory(&pItem->member.para, &pdi->member.para, sizeof(ME_Paragraph)); pItem->member.para.pFmt = ALLOC_OBJ(PARAFORMAT2); CopyMemory(pItem->member.para.pFmt, pdi->member.para.pFmt, sizeof(PARAFORMAT2)); break; case diUndoInsertRun: assert(pdi); CopyMemory(&pItem->member.run, &pdi->member.run, sizeof(ME_Run)); pItem->member.run.strText = ME_StrDup(pItem->member.run.strText); ME_AddRefStyle(pItem->member.run.style); break; case diUndoSetCharFormat: case diUndoSetDefaultCharFormat: break; case diUndoDeleteRun: case diUndoJoinParagraphs: break; case diUndoSplitParagraph: pItem->member.para.pFmt = ALLOC_OBJ(PARAFORMAT2); pItem->member.para.pFmt->cbSize = sizeof(PARAFORMAT2); pItem->member.para.pFmt->dwMask = 0; 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->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) 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; } }