ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

para.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(&copy, 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, &para, &para_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, &para, &para_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.