Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpara.c
Go to the documentation of this file.
00001 /* 00002 * RichEdit - functions working on paragraphs of text (diParagraph). 00003 * 00004 * Copyright 2004 by Krzysztof Foltman 00005 * Copyright 2006 by Phil Krylov 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "editor.h" 00023 00024 WINE_DEFAULT_DEBUG_CHANNEL(richedit); 00025 00026 void ME_MakeFirstParagraph(ME_TextEditor *editor) 00027 { 00028 ME_Context c; 00029 CHARFORMAT2W cf; 00030 LOGFONTW lf; 00031 HFONT hf; 00032 ME_TextBuffer *text = editor->pBuffer; 00033 ME_DisplayItem *para = ME_MakeDI(diParagraph); 00034 ME_DisplayItem *run; 00035 ME_Style *style; 00036 ME_String *eol_str; 00037 WCHAR cr_lf[] = {'\r','\n',0}; 00038 00039 ME_InitContext(&c, editor, ITextHost_TxGetDC(editor->texthost)); 00040 00041 hf = GetStockObject(SYSTEM_FONT); 00042 assert(hf); 00043 GetObjectW(hf, sizeof(LOGFONTW), &lf); 00044 ZeroMemory(&cf, sizeof(cf)); 00045 cf.cbSize = sizeof(cf); 00046 cf.dwMask = CFM_BACKCOLOR|CFM_COLOR|CFM_FACE|CFM_SIZE|CFM_CHARSET; 00047 cf.dwMask |= CFM_ALLCAPS|CFM_BOLD|CFM_DISABLED|CFM_EMBOSS|CFM_HIDDEN; 00048 cf.dwMask |= CFM_IMPRINT|CFM_ITALIC|CFM_LINK|CFM_OUTLINE|CFM_PROTECTED; 00049 cf.dwMask |= CFM_REVISED|CFM_SHADOW|CFM_SMALLCAPS|CFM_STRIKEOUT; 00050 cf.dwMask |= CFM_SUBSCRIPT|CFM_UNDERLINETYPE|CFM_WEIGHT; 00051 00052 cf.dwEffects = CFE_AUTOCOLOR | CFE_AUTOBACKCOLOR; 00053 lstrcpyW(cf.szFaceName, lf.lfFaceName); 00054 /* Convert system font height from logical units to twips for cf.yHeight */ 00055 cf.yHeight = (lf.lfHeight * 72 * 1440) / (c.dpi.cy * c.dpi.cy); 00056 if (lf.lfWeight > FW_NORMAL) cf.dwEffects |= CFE_BOLD; 00057 cf.wWeight = lf.lfWeight; 00058 if (lf.lfItalic) cf.dwEffects |= CFE_ITALIC; 00059 cf.bUnderlineType = (lf.lfUnderline) ? CFU_CF1UNDERLINE : CFU_UNDERLINENONE; 00060 if (lf.lfStrikeOut) cf.dwEffects |= CFE_STRIKEOUT; 00061 cf.bPitchAndFamily = lf.lfPitchAndFamily; 00062 cf.bCharSet = lf.lfCharSet; 00063 00064 style = ME_MakeStyle(&cf); 00065 text->pDefaultStyle = style; 00066 00067 eol_str = ME_MakeStringN(cr_lf, editor->bEmulateVersion10 ? 2 : 1); 00068 run = ME_MakeRun(style, eol_str, MERF_ENDPARA); 00069 run->member.run.nCharOfs = 0; 00070 00071 ME_InsertBefore(text->pLast, para); 00072 ME_InsertBefore(text->pLast, run); 00073 para->member.para.prev_para = text->pFirst; 00074 para->member.para.next_para = text->pLast; 00075 text->pFirst->member.para.next_para = para; 00076 text->pLast->member.para.prev_para = para; 00077 00078 text->pLast->member.para.nCharOfs = editor->bEmulateVersion10 ? 2 : 1; 00079 00080 ME_DestroyContext(&c); 00081 } 00082 00083 static void ME_MarkForWrapping(ME_TextEditor *editor, ME_DisplayItem *first, const ME_DisplayItem *last) 00084 { 00085 while(first != last) 00086 { 00087 first->member.para.nFlags |= MEPF_REWRAP; 00088 first = first->member.para.next_para; 00089 } 00090 } 00091 00092 void ME_MarkAllForWrapping(ME_TextEditor *editor) 00093 { 00094 ME_MarkForWrapping(editor, editor->pBuffer->pFirst->member.para.next_para, editor->pBuffer->pLast); 00095 } 00096 00097 void ME_MarkForPainting(ME_TextEditor *editor, ME_DisplayItem *first, const ME_DisplayItem *last) 00098 { 00099 while(first != last && first) 00100 { 00101 first->member.para.nFlags |= MEPF_REPAINT; 00102 first = first->member.para.next_para; 00103 } 00104 } 00105 00106 static void ME_UpdateTableFlags(ME_DisplayItem *para) 00107 { 00108 para->member.para.pFmt->dwMask |= PFM_TABLE|PFM_TABLEROWDELIMITER; 00109 if (para->member.para.pCell) { 00110 para->member.para.nFlags |= MEPF_CELL; 00111 } else { 00112 para->member.para.nFlags &= ~MEPF_CELL; 00113 } 00114 if (para->member.para.nFlags & MEPF_ROWEND) { 00115 para->member.para.pFmt->wEffects |= PFE_TABLEROWDELIMITER; 00116 } else { 00117 para->member.para.pFmt->wEffects &= ~PFE_TABLEROWDELIMITER; 00118 } 00119 if (para->member.para.nFlags & (MEPF_ROWSTART|MEPF_CELL|MEPF_ROWEND)) 00120 para->member.para.pFmt->wEffects |= PFE_TABLE; 00121 else 00122 para->member.para.pFmt->wEffects &= ~PFE_TABLE; 00123 } 00124 00125 static BOOL ME_SetParaFormat(ME_TextEditor *editor, ME_DisplayItem *para, const PARAFORMAT2 *pFmt) 00126 { 00127 PARAFORMAT2 copy; 00128 DWORD dwMask; 00129 00130 assert(para->member.para.pFmt->cbSize == sizeof(PARAFORMAT2)); 00131 dwMask = pFmt->dwMask; 00132 if (pFmt->cbSize < sizeof(PARAFORMAT)) 00133 return FALSE; 00134 else if (pFmt->cbSize < sizeof(PARAFORMAT2)) 00135 dwMask &= PFM_ALL; 00136 else 00137 dwMask &= PFM_ALL2; 00138 00139 ME_AddUndoItem(editor, diUndoSetParagraphFormat, para); 00140 00141 copy = *para->member.para.pFmt; 00142 00143 #define COPY_FIELD(m, f) \ 00144 if (dwMask & (m)) { \ 00145 para->member.para.pFmt->dwMask |= m; \ 00146 para->member.para.pFmt->f = pFmt->f; \ 00147 } 00148 00149 COPY_FIELD(PFM_NUMBERING, wNumbering); 00150 COPY_FIELD(PFM_STARTINDENT, dxStartIndent); 00151 if (dwMask & PFM_OFFSETINDENT) 00152 para->member.para.pFmt->dxStartIndent += pFmt->dxStartIndent; 00153 COPY_FIELD(PFM_RIGHTINDENT, dxRightIndent); 00154 COPY_FIELD(PFM_OFFSET, dxOffset); 00155 COPY_FIELD(PFM_ALIGNMENT, wAlignment); 00156 if (dwMask & PFM_TABSTOPS) 00157 { 00158 para->member.para.pFmt->cTabCount = pFmt->cTabCount; 00159 memcpy(para->member.para.pFmt->rgxTabs, pFmt->rgxTabs, pFmt->cTabCount*sizeof(LONG)); 00160 } 00161 00162 if (dwMask & (PFM_ALL2 & ~PFM_ALL)) 00163 { 00164 /* PARAFORMAT2 fields */ 00165 00166 #define EFFECTS_MASK (PFM_RTLPARA|PFM_KEEP|PFM_KEEPNEXT|PFM_PAGEBREAKBEFORE| \ 00167 PFM_NOLINENUMBER|PFM_NOWIDOWCONTROL|PFM_DONOTHYPHEN|PFM_SIDEBYSIDE| \ 00168 PFM_TABLE) 00169 /* we take for granted that PFE_xxx is the hiword of the corresponding PFM_xxx */ 00170 if (dwMask & EFFECTS_MASK) { 00171 para->member.para.pFmt->dwMask |= dwMask & EFFECTS_MASK; 00172 para->member.para.pFmt->wEffects &= ~HIWORD(dwMask); 00173 para->member.para.pFmt->wEffects |= pFmt->wEffects & HIWORD(dwMask); 00174 } 00175 #undef EFFECTS_MASK 00176 00177 COPY_FIELD(PFM_SPACEBEFORE, dySpaceBefore); 00178 COPY_FIELD(PFM_SPACEAFTER, dySpaceAfter); 00179 COPY_FIELD(PFM_LINESPACING, dyLineSpacing); 00180 COPY_FIELD(PFM_STYLE, sStyle); 00181 COPY_FIELD(PFM_LINESPACING, bLineSpacingRule); 00182 COPY_FIELD(PFM_SHADING, wShadingWeight); 00183 COPY_FIELD(PFM_SHADING, wShadingStyle); 00184 COPY_FIELD(PFM_NUMBERINGSTART, wNumberingStart); 00185 COPY_FIELD(PFM_NUMBERINGSTYLE, wNumberingStyle); 00186 COPY_FIELD(PFM_NUMBERINGTAB, wNumberingTab); 00187 COPY_FIELD(PFM_BORDER, wBorderSpace); 00188 COPY_FIELD(PFM_BORDER, wBorderWidth); 00189 COPY_FIELD(PFM_BORDER, wBorders); 00190 } 00191 00192 para->member.para.pFmt->dwMask |= dwMask; 00193 #undef COPY_FIELD 00194 00195 if (memcmp(©, para->member.para.pFmt, sizeof(PARAFORMAT2))) 00196 para->member.para.nFlags |= MEPF_REWRAP; 00197 00198 return TRUE; 00199 } 00200 00201 /* split paragraph at the beginning of the run */ 00202 ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, 00203 ME_Style *style, ME_String *eol_str, 00204 int paraFlags) 00205 { 00206 ME_DisplayItem *next_para = NULL; 00207 ME_DisplayItem *run_para = NULL; 00208 ME_DisplayItem *new_para = ME_MakeDI(diParagraph); 00209 ME_DisplayItem *end_run; 00210 ME_UndoItem *undo = NULL; 00211 int ofs, i; 00212 ME_DisplayItem *pp; 00213 int run_flags = MERF_ENDPARA; 00214 00215 if (!editor->bEmulateVersion10) { /* v4.1 */ 00216 /* At most 1 of MEPF_CELL, MEPF_ROWSTART, or MEPF_ROWEND should be set. */ 00217 assert(!(paraFlags & ~(MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND))); 00218 assert(!(paraFlags & (paraFlags-1))); 00219 if (paraFlags == MEPF_CELL) 00220 run_flags |= MERF_ENDCELL; 00221 else if (paraFlags == MEPF_ROWSTART) 00222 run_flags |= MERF_TABLESTART|MERF_HIDDEN; 00223 } else { /* v1.0 - v3.0 */ 00224 assert(!(paraFlags & (MEPF_CELL|MEPF_ROWSTART|MEPF_ROWEND))); 00225 } 00226 end_run = ME_MakeRun(style, eol_str, run_flags); 00227 00228 assert(run->type == diRun); 00229 run_para = ME_GetParagraph(run); 00230 assert(run_para->member.para.pFmt->cbSize == sizeof(PARAFORMAT2)); 00231 00232 ofs = end_run->member.run.nCharOfs = run->member.run.nCharOfs; 00233 next_para = run_para->member.para.next_para; 00234 assert(next_para == ME_FindItemFwd(run_para, diParagraphOrEnd)); 00235 00236 undo = ME_AddUndoItem(editor, diUndoJoinParagraphs, NULL); 00237 if (undo) 00238 undo->nStart = run_para->member.para.nCharOfs + ofs; 00239 00240 /* Update selection cursors to point to the correct paragraph. */ 00241 for (i = 0; i < editor->nCursors; i++) { 00242 if (editor->pCursors[i].pPara == run_para && 00243 run->member.run.nCharOfs <= editor->pCursors[i].pRun->member.run.nCharOfs) 00244 { 00245 editor->pCursors[i].pPara = new_para; 00246 } 00247 } 00248 00249 /* the new paragraph will have a different starting offset, so let's update its runs */ 00250 pp = run; 00251 while(pp->type == diRun) { 00252 pp->member.run.nCharOfs -= ofs; 00253 pp = ME_FindItemFwd(pp, diRunOrParagraphOrEnd); 00254 } 00255 new_para->member.para.nCharOfs = run_para->member.para.nCharOfs + ofs; 00256 new_para->member.para.nCharOfs += eol_str->nLen; 00257 new_para->member.para.nFlags = MEPF_REWRAP; 00258 00259 /* FIXME initialize format style and call ME_SetParaFormat blah blah */ 00260 *new_para->member.para.pFmt = *run_para->member.para.pFmt; 00261 new_para->member.para.border = run_para->member.para.border; 00262 00263 /* insert paragraph into paragraph double linked list */ 00264 new_para->member.para.prev_para = run_para; 00265 new_para->member.para.next_para = next_para; 00266 run_para->member.para.next_para = new_para; 00267 next_para->member.para.prev_para = new_para; 00268 00269 /* insert end run of the old paragraph, and new paragraph, into DI double linked list */ 00270 ME_InsertBefore(run, new_para); 00271 ME_InsertBefore(new_para, end_run); 00272 00273 if (!editor->bEmulateVersion10) { /* v4.1 */ 00274 if (paraFlags & (MEPF_ROWSTART|MEPF_CELL)) 00275 { 00276 ME_DisplayItem *cell = ME_MakeDI(diCell); 00277 ME_InsertBefore(new_para, cell); 00278 new_para->member.para.pCell = cell; 00279 cell->member.cell.next_cell = NULL; 00280 if (paraFlags & MEPF_ROWSTART) 00281 { 00282 run_para->member.para.nFlags |= MEPF_ROWSTART; 00283 cell->member.cell.prev_cell = NULL; 00284 cell->member.cell.parent_cell = run_para->member.para.pCell; 00285 if (run_para->member.para.pCell) 00286 cell->member.cell.nNestingLevel = run_para->member.para.pCell->member.cell.nNestingLevel + 1; 00287 else 00288 cell->member.cell.nNestingLevel = 1; 00289 } else { 00290 cell->member.cell.prev_cell = run_para->member.para.pCell; 00291 assert(cell->member.cell.prev_cell); 00292 cell->member.cell.prev_cell->member.cell.next_cell = cell; 00293 assert(run_para->member.para.nFlags & MEPF_CELL); 00294 assert(!(run_para->member.para.nFlags & MEPF_ROWSTART)); 00295 cell->member.cell.nNestingLevel = cell->member.cell.prev_cell->member.cell.nNestingLevel; 00296 cell->member.cell.parent_cell = cell->member.cell.prev_cell->member.cell.parent_cell; 00297 } 00298 } else if (paraFlags & MEPF_ROWEND) { 00299 run_para->member.para.nFlags |= MEPF_ROWEND; 00300 run_para->member.para.pCell = run_para->member.para.pCell->member.cell.parent_cell; 00301 new_para->member.para.pCell = run_para->member.para.pCell; 00302 assert(run_para->member.para.prev_para->member.para.nFlags & MEPF_CELL); 00303 assert(!(run_para->member.para.prev_para->member.para.nFlags & MEPF_ROWSTART)); 00304 if (new_para->member.para.pCell != new_para->member.para.next_para->member.para.pCell 00305 && new_para->member.para.next_para->member.para.pCell 00306 && !new_para->member.para.next_para->member.para.pCell->member.cell.prev_cell) 00307 { 00308 /* Row starts just after the row that was ended. */ 00309 new_para->member.para.nFlags |= MEPF_ROWSTART; 00310 } 00311 } else { 00312 new_para->member.para.pCell = run_para->member.para.pCell; 00313 } 00314 ME_UpdateTableFlags(run_para); 00315 ME_UpdateTableFlags(new_para); 00316 } 00317 00318 /* force rewrap of the */ 00319 run_para->member.para.prev_para->member.para.nFlags |= MEPF_REWRAP; 00320 new_para->member.para.prev_para->member.para.nFlags |= MEPF_REWRAP; 00321 00322 /* we've added the end run, so we need to modify nCharOfs in the next paragraphs */ 00323 ME_PropagateCharOffset(next_para, eol_str->nLen); 00324 editor->nParagraphs++; 00325 00326 return new_para; 00327 } 00328 00329 /* join tp with tp->member.para.next_para, keeping tp's style; this 00330 * is consistent with the original */ 00331 ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp, 00332 BOOL keepFirstParaFormat) 00333 { 00334 ME_DisplayItem *pNext, *pFirstRunInNext, *pRun, *pTmp; 00335 int i, shift; 00336 ME_UndoItem *undo = NULL; 00337 int end_len; 00338 CHARFORMAT2W fmt; 00339 ME_Cursor startCur, endCur; 00340 00341 assert(tp->type == diParagraph); 00342 assert(tp->member.para.next_para); 00343 assert(tp->member.para.next_para->type == diParagraph); 00344 00345 pNext = tp->member.para.next_para; 00346 00347 /* Need to locate end-of-paragraph run here, in order to know end_len */ 00348 pRun = ME_FindItemBack(pNext, diRunOrParagraph); 00349 00350 assert(pRun); 00351 assert(pRun->type == diRun); 00352 assert(pRun->member.run.nFlags & MERF_ENDPARA); 00353 00354 end_len = pRun->member.run.strText->nLen; 00355 00356 /* null char format operation to store the original char format for the ENDPARA run */ 00357 ME_InitCharFormat2W(&fmt); 00358 endCur.pPara = pNext; 00359 endCur.pRun = ME_FindItemFwd(pNext, diRun); 00360 endCur.nOffset = 0; 00361 startCur = endCur; 00362 ME_PrevRun(&startCur.pPara, &startCur.pRun); 00363 ME_SetCharFormat(editor, &startCur, &endCur, &fmt); 00364 00365 undo = ME_AddUndoItem(editor, diUndoSplitParagraph, pNext); 00366 if (undo) 00367 { 00368 undo->nStart = pNext->member.para.nCharOfs - end_len; 00369 undo->eol_str = pRun->member.run.strText; 00370 pRun->member.run.strText = NULL; /* Avoid freeing the string */ 00371 } 00372 if (!keepFirstParaFormat) 00373 { 00374 ME_AddUndoItem(editor, diUndoSetParagraphFormat, tp); 00375 *tp->member.para.pFmt = *pNext->member.para.pFmt; 00376 tp->member.para.border = pNext->member.para.border; 00377 } 00378 00379 if (!editor->bEmulateVersion10) { /* v4.1 */ 00380 /* Table cell/row properties are always moved over from the removed para. */ 00381 tp->member.para.nFlags = pNext->member.para.nFlags; 00382 tp->member.para.pCell = pNext->member.para.pCell; 00383 00384 /* Remove cell boundary if it is between the end paragraph run and the next 00385 * paragraph display item. */ 00386 pTmp = pRun->next; 00387 while (pTmp != pNext) { 00388 if (pTmp->type == diCell) 00389 { 00390 ME_Cell *pCell = &pTmp->member.cell; 00391 if (undo) 00392 { 00393 assert(!(undo->di.member.para.nFlags & MEPF_ROWEND)); 00394 if (!(undo->di.member.para.nFlags & MEPF_ROWSTART)) 00395 undo->di.member.para.nFlags |= MEPF_CELL; 00396 undo->di.member.para.pCell = ALLOC_OBJ(ME_DisplayItem); 00397 *undo->di.member.para.pCell = *pTmp; 00398 undo->di.member.para.pCell->next = NULL; 00399 undo->di.member.para.pCell->prev = NULL; 00400 undo->di.member.para.pCell->member.cell.next_cell = NULL; 00401 undo->di.member.para.pCell->member.cell.prev_cell = NULL; 00402 } 00403 ME_Remove(pTmp); 00404 if (pCell->prev_cell) 00405 pCell->prev_cell->member.cell.next_cell = pCell->next_cell; 00406 if (pCell->next_cell) 00407 pCell->next_cell->member.cell.prev_cell = pCell->prev_cell; 00408 ME_DestroyDisplayItem(pTmp); 00409 break; 00410 } 00411 pTmp = pTmp->next; 00412 } 00413 } 00414 00415 shift = pNext->member.para.nCharOfs - tp->member.para.nCharOfs - end_len; 00416 00417 pFirstRunInNext = ME_FindItemFwd(pNext, diRunOrParagraph); 00418 00419 assert(pFirstRunInNext->type == diRun); 00420 00421 /* Update selection cursors so they don't point to the removed end 00422 * paragraph run, and point to the correct paragraph. */ 00423 for (i=0; i < editor->nCursors; i++) { 00424 if (editor->pCursors[i].pRun == pRun) { 00425 editor->pCursors[i].pRun = pFirstRunInNext; 00426 editor->pCursors[i].nOffset = 0; 00427 } else if (editor->pCursors[i].pPara == pNext) { 00428 editor->pCursors[i].pPara = tp; 00429 } 00430 } 00431 00432 pTmp = pNext; 00433 do { 00434 pTmp = ME_FindItemFwd(pTmp, diRunOrParagraphOrEnd); 00435 if (pTmp->type != diRun) 00436 break; 00437 TRACE("shifting \"%s\" by %d (previous %d)\n", debugstr_w(pTmp->member.run.strText->szData), shift, pTmp->member.run.nCharOfs); 00438 pTmp->member.run.nCharOfs += shift; 00439 } while(1); 00440 00441 ME_Remove(pRun); 00442 ME_DestroyDisplayItem(pRun); 00443 00444 if (editor->pLastSelStartPara == pNext) 00445 editor->pLastSelStartPara = tp; 00446 if (editor->pLastSelEndPara == pNext) 00447 editor->pLastSelEndPara = tp; 00448 00449 tp->member.para.next_para = pNext->member.para.next_para; 00450 pNext->member.para.next_para->member.para.prev_para = tp; 00451 ME_Remove(pNext); 00452 ME_DestroyDisplayItem(pNext); 00453 00454 ME_PropagateCharOffset(tp->member.para.next_para, -end_len); 00455 00456 ME_CheckCharOffsets(editor); 00457 00458 editor->nParagraphs--; 00459 tp->member.para.nFlags |= MEPF_REWRAP; 00460 return tp; 00461 } 00462 00463 ME_DisplayItem *ME_GetParagraph(ME_DisplayItem *item) { 00464 return ME_FindItemBackOrHere(item, diParagraph); 00465 } 00466 00467 void ME_DumpParaStyleToBuf(const PARAFORMAT2 *pFmt, char buf[2048]) 00468 { 00469 char *p; 00470 p = buf; 00471 00472 #define DUMP(mask, name, fmt, field) \ 00473 if (pFmt->dwMask & (mask)) p += sprintf(p, "%-22s" fmt "\n", name, pFmt->field); \ 00474 else p += sprintf(p, "%-22sN/A\n", name); 00475 00476 /* we take for granted that PFE_xxx is the hiword of the corresponding PFM_xxx */ 00477 #define DUMP_EFFECT(mask, name) \ 00478 p += sprintf(p, "%-22s%s\n", name, (pFmt->dwMask & (mask)) ? ((pFmt->wEffects & ((mask) >> 16)) ? "yes" : "no") : "N/A"); 00479 00480 DUMP(PFM_NUMBERING, "Numbering:", "%u", wNumbering); 00481 DUMP_EFFECT(PFM_DONOTHYPHEN, "Disable auto-hyphen:"); 00482 DUMP_EFFECT(PFM_KEEP, "No page break in para:"); 00483 DUMP_EFFECT(PFM_KEEPNEXT, "No page break in para & next:"); 00484 DUMP_EFFECT(PFM_NOLINENUMBER, "No line number:"); 00485 DUMP_EFFECT(PFM_NOWIDOWCONTROL, "No widow & orphan:"); 00486 DUMP_EFFECT(PFM_PAGEBREAKBEFORE, "Page break before:"); 00487 DUMP_EFFECT(PFM_RTLPARA, "RTL para:"); 00488 DUMP_EFFECT(PFM_SIDEBYSIDE, "Side by side:"); 00489 DUMP_EFFECT(PFM_TABLE, "Table:"); 00490 DUMP(PFM_OFFSETINDENT, "Offset indent:", "%d", dxStartIndent); 00491 DUMP(PFM_STARTINDENT, "Start indent:", "%d", dxStartIndent); 00492 DUMP(PFM_RIGHTINDENT, "Right indent:", "%d", dxRightIndent); 00493 DUMP(PFM_OFFSET, "Offset:", "%d", dxOffset); 00494 if (pFmt->dwMask & PFM_ALIGNMENT) { 00495 switch (pFmt->wAlignment) { 00496 case PFA_LEFT : p += sprintf(p, "Alignment: left\n"); break; 00497 case PFA_RIGHT : p += sprintf(p, "Alignment: right\n"); break; 00498 case PFA_CENTER : p += sprintf(p, "Alignment: center\n"); break; 00499 case PFA_JUSTIFY: p += sprintf(p, "Alignment: justify\n"); break; 00500 default : p += sprintf(p, "Alignment: incorrect %d\n", pFmt->wAlignment); break; 00501 } 00502 } 00503 else p += sprintf(p, "Alignment: N/A\n"); 00504 DUMP(PFM_TABSTOPS, "Tab Stops:", "%d", cTabCount); 00505 if (pFmt->dwMask & PFM_TABSTOPS) { 00506 int i; 00507 p += sprintf(p, "\t"); 00508 for (i = 0; i < pFmt->cTabCount; i++) p += sprintf(p, "%x ", pFmt->rgxTabs[i]); 00509 p += sprintf(p, "\n"); 00510 } 00511 DUMP(PFM_SPACEBEFORE, "Space Before:", "%d", dySpaceBefore); 00512 DUMP(PFM_SPACEAFTER, "Space After:", "%d", dySpaceAfter); 00513 DUMP(PFM_LINESPACING, "Line spacing:", "%d", dyLineSpacing); 00514 DUMP(PFM_STYLE, "Text style:", "%d", sStyle); 00515 DUMP(PFM_LINESPACING, "Line spacing rule:", "%u", bLineSpacingRule); 00516 /* bOutlineLevel should be 0 */ 00517 DUMP(PFM_SHADING, "Shading Weigth:", "%u", wShadingWeight); 00518 DUMP(PFM_SHADING, "Shading Style:", "%u", wShadingStyle); 00519 DUMP(PFM_NUMBERINGSTART, "Numbering Start:", "%u", wNumberingStart); 00520 DUMP(PFM_NUMBERINGSTYLE, "Numbering Style:", "0x%x", wNumberingStyle); 00521 DUMP(PFM_NUMBERINGTAB, "Numbering Tab:", "%u", wNumberingStyle); 00522 DUMP(PFM_BORDER, "Border Space:", "%u", wBorderSpace); 00523 DUMP(PFM_BORDER, "Border Width:", "%u", wBorderWidth); 00524 DUMP(PFM_BORDER, "Borders:", "%u", wBorders); 00525 00526 #undef DUMP 00527 #undef DUMP_EFFECT 00528 } 00529 00530 void 00531 ME_GetSelectionParas(ME_TextEditor *editor, ME_DisplayItem **para, ME_DisplayItem **para_end) 00532 { 00533 ME_Cursor *pEndCursor = &editor->pCursors[1]; 00534 00535 *para = editor->pCursors[0].pPara; 00536 *para_end = editor->pCursors[1].pPara; 00537 if (*para == *para_end) 00538 return; 00539 00540 if ((*para_end)->member.para.nCharOfs < (*para)->member.para.nCharOfs) { 00541 ME_DisplayItem *tmp = *para; 00542 00543 *para = *para_end; 00544 *para_end = tmp; 00545 pEndCursor = &editor->pCursors[0]; 00546 } 00547 00548 /* The paragraph at the end of a non-empty selection isn't included 00549 * if the selection ends at the start of the paragraph. */ 00550 if (!pEndCursor->pRun->member.run.nCharOfs && !pEndCursor->nOffset) 00551 *para_end = (*para_end)->member.para.prev_para; 00552 } 00553 00554 00555 BOOL ME_SetSelectionParaFormat(ME_TextEditor *editor, const PARAFORMAT2 *pFmt) 00556 { 00557 ME_DisplayItem *para, *para_end; 00558 00559 ME_GetSelectionParas(editor, ¶, ¶_end); 00560 00561 do { 00562 ME_SetParaFormat(editor, para, pFmt); 00563 if (para == para_end) 00564 break; 00565 para = para->member.para.next_para; 00566 } while(1); 00567 00568 return TRUE; 00569 } 00570 00571 static void ME_GetParaFormat(ME_TextEditor *editor, 00572 const ME_DisplayItem *para, 00573 PARAFORMAT2 *pFmt) 00574 { 00575 UINT cbSize = pFmt->cbSize; 00576 if (pFmt->cbSize >= sizeof(PARAFORMAT2)) { 00577 *pFmt = *para->member.para.pFmt; 00578 } else { 00579 CopyMemory(pFmt, para->member.para.pFmt, pFmt->cbSize); 00580 pFmt->dwMask &= PFM_ALL; 00581 } 00582 pFmt->cbSize = cbSize; 00583 } 00584 00585 void ME_GetSelectionParaFormat(ME_TextEditor *editor, PARAFORMAT2 *pFmt) 00586 { 00587 ME_DisplayItem *para, *para_end; 00588 PARAFORMAT2 *curFmt; 00589 00590 if (pFmt->cbSize < sizeof(PARAFORMAT)) { 00591 pFmt->dwMask = 0; 00592 return; 00593 } 00594 00595 ME_GetSelectionParas(editor, ¶, ¶_end); 00596 00597 ME_GetParaFormat(editor, para, pFmt); 00598 00599 /* Invalidate values that change across the selected paragraphs. */ 00600 while (para != para_end) 00601 { 00602 para = para->member.para.next_para; 00603 curFmt = para->member.para.pFmt; 00604 00605 #define CHECK_FIELD(m, f) \ 00606 if (pFmt->f != curFmt->f) pFmt->dwMask &= ~(m); 00607 00608 CHECK_FIELD(PFM_NUMBERING, wNumbering); 00609 CHECK_FIELD(PFM_STARTINDENT, dxStartIndent); 00610 CHECK_FIELD(PFM_RIGHTINDENT, dxRightIndent); 00611 CHECK_FIELD(PFM_OFFSET, dxOffset); 00612 CHECK_FIELD(PFM_ALIGNMENT, wAlignment); 00613 if (pFmt->dwMask & PFM_TABSTOPS) { 00614 if (pFmt->cTabCount != para->member.para.pFmt->cTabCount || 00615 memcmp(pFmt->rgxTabs, curFmt->rgxTabs, curFmt->cTabCount*sizeof(int))) 00616 pFmt->dwMask &= ~PFM_TABSTOPS; 00617 } 00618 00619 if (pFmt->dwMask >= sizeof(PARAFORMAT2)) 00620 { 00621 pFmt->dwMask &= ~((pFmt->wEffects ^ curFmt->wEffects) << 16); 00622 CHECK_FIELD(PFM_SPACEBEFORE, dySpaceBefore); 00623 CHECK_FIELD(PFM_SPACEAFTER, dySpaceAfter); 00624 CHECK_FIELD(PFM_LINESPACING, dyLineSpacing); 00625 CHECK_FIELD(PFM_STYLE, sStyle); 00626 CHECK_FIELD(PFM_SPACEAFTER, bLineSpacingRule); 00627 CHECK_FIELD(PFM_SHADING, wShadingWeight); 00628 CHECK_FIELD(PFM_SHADING, wShadingStyle); 00629 CHECK_FIELD(PFM_NUMBERINGSTART, wNumberingStart); 00630 CHECK_FIELD(PFM_NUMBERINGSTYLE, wNumberingStyle); 00631 CHECK_FIELD(PFM_NUMBERINGTAB, wNumberingTab); 00632 CHECK_FIELD(PFM_BORDER, wBorderSpace); 00633 CHECK_FIELD(PFM_BORDER, wBorderWidth); 00634 CHECK_FIELD(PFM_BORDER, wBorders); 00635 } 00636 #undef CHECK_FIELD 00637 } 00638 } 00639 00640 void ME_SetDefaultParaFormat(PARAFORMAT2 *pFmt) 00641 { 00642 ZeroMemory(pFmt, sizeof(PARAFORMAT2)); 00643 pFmt->cbSize = sizeof(PARAFORMAT2); 00644 pFmt->dwMask = PFM_ALL2; 00645 pFmt->wAlignment = PFA_LEFT; 00646 pFmt->sStyle = -1; 00647 pFmt->bOutlineLevel = TRUE; 00648 } Generated on Sat May 26 2012 04:24:31 for ReactOS by
1.7.6.1
|