📄 mimerichtextdraw.c
字号:
tline = tline->next; } }//// See if we need to re-position the lines vertically. This will update// both scroll bars.// int oldVsbVal = vsbVal; if ( placeNeeded || forcePlace ) PlaceLines(begLine);//// Update horizontal scroll bar if necessary. There must be room for at least// one complete line before we turn the scroll bars on.// else if ( !textSW ) { WArgList args; int lineHt = pub->LineHeight(); int sbSize = scrollBoff - noScrollBoff; int drawHtWithSB = drawHt; if ( !hsbOn ) drawHtWithSB -= sbSize; if ( (textWd > (int)drawWd) && (drawHtWithSB >= lineHt) ) { if ( !hsbOn ) { XtVaSetValues(hlForm, XmNbottomOffset, scrollBoff, NULL); drawHt -= sbSize; hsbOn = True; } } // End if horizontal scroll bar needed else { if ( hsbOn && !hsbAlwaysOn ) { XtVaSetValues(hlForm, XmNbottomOffset, noScrollBoff, NULL); drawHt += sbSize; hsbOn = False; } } // End if horizontal scroll bar not needed hsbMax = MAX((int)drawWd, textWd); int ss = MIN((int)drawWd, hsbMax); if ( hsbVal + ss > hsbMax ) hsbVal = hsbMax - ss; int pi = drawWd - pub->CharWidth(); if ( pi <= 0 ) pi = drawWd; args.Value(hsbVal); args.Maximum(hsbMax); args.MappedWhenManaged(hsbOn); args.SliderSize(ss); args.PageIncrement(pi); XtSetValues(textHSB, ARGS); } // End if horizontal scroll bar needs to be checked//// Redraw the affected lines. Draw all lines if the scroll bar moved.// int ymin, ht; if ( vsbVal != oldVsbVal ) { ymin = 0; ht = drawHt; } else { ymin = begLine->bounds.ymin - vsbVal; if ( ymin < 0 ) ymin = 0; int ymax; if ( placeNeeded || forcePlace ) ymax = drawHt - 1; else ymax = endLine->bounds.ymax - vsbVal; ht = ymax - ymin + 1; if ( ht > (int)drawHt ) ht = drawHt; } RectC area(0, ymin, drawWd, ht); DrawScreen(area);//// Call text change callbacks// CallCallbacks(changeCalls, pub);} // End LinesChanged/*---------------------------------------------------------------------- * Set the position of all lines */voidMimeRichTextP::PlaceLines(TextLineC *startLine){ if ( startLine && startLine->prev ) textY = startLine->prev->bounds.ymax + 1 + lineSpacing; else { startLine = topTextLine; textY = marginHt + 2; // This will allow the accent characters to be // displayed on the top line } TextLineC *line = startLine; while ( line ) { SetLinePosition(line, textY); textY += line->bounds.ht + lineSpacing; line = line->next; } if ( startLine ) textY -= lineSpacing; textY += marginHt;//// Clear out the bottom part// if ( realized && textY < (int)textHt ) { int y = textY - vsbVal; if ( y >= 0 && y <= (int)drawHt ) { XSetForeground(halApp->display, textGC, bgColor); Drawable drawto = pub->DrawTo(); XFillRectangle(halApp->display, drawto, textGC, 0, y, drawWd, drawHt - y + 1); if ( drawto != textWin ) XFillRectangle(halApp->display, textWin, textGC, 0, y, drawWd, drawHt - y + 1); XSetForeground(halApp->display, textGC, fgColor); } }//// If we're in a scrolled window, see if we need to resize ourself.// if ( textSW ) { Dimension newHt = MAX(textY, (int)(clipHt-marginHt2-1)); if ( newHt != textHt ) { drawHt = textHt = newHt; if ( debuglev > 1 ) cout <<"setting height to " <<textHt NL; XtVaSetValues(textDA, XmNheight, textHt+marginHt2, 0); } // End if height changed } // End if height can be adjusted//// If we're not in a scrolled window, update the scroll bars// else { textHt = textY;//// Update the scroll bars// static Boolean formatAgain = False; if ( !formatAgain ) { WArgList args;//// See if we need a vertical scroll bar// args.Reset(); if ( textHt > (int)maxHt && (int)drawWd >= 2*pub->CharWidth() ) { if ( !vsbOn ) { XtVaSetValues(hlForm, XmNrightOffset, scrollRoff, NULL); drawWd -= (scrollRoff - noScrollRoff); formatAgain = True; vsbOn = True; } } // End if vertical scroll bar needed else { if ( vsbOn && !vsbAlwaysOn ) { XtVaSetValues(hlForm, XmNrightOffset, noScrollRoff, NULL); drawWd += (scrollRoff - noScrollRoff); formatAgain = True; vsbOn = False; } } // End if vertical scroll bar not needed if ( formatAgain ) FormatScreen(); formatAgain = False; vsbMax = MAX((int)drawHt, textHt); int ss = MIN((int)drawHt, vsbMax); if ( vsbVal + ss > vsbMax ) vsbVal = vsbMax - ss; int pi = drawHt - pub->LineHeight(); if ( pi <= 0 ) pi = drawHt; args.Value(vsbVal); args.Maximum(vsbMax); args.MappedWhenManaged(vsbOn); args.SliderSize(ss); args.PageIncrement(pi); XtSetValues(textVSB, ARGS);//// See if we need a horizontal scroll bar. There must be room for at least// one complete line before we turn the scroll bar on.// args.Reset(); int lineHt = pub->LineHeight(); int sbSize = scrollBoff - noScrollBoff; int drawHtWithSB = drawHt; if ( !hsbOn ) drawHtWithSB -= sbSize; if ( (textWd > (int)drawWd) && (drawHtWithSB >= lineHt) ) { if ( !hsbOn ) { XtVaSetValues(hlForm, XmNbottomOffset, scrollBoff, NULL); drawHt -= sbSize; hsbOn = True; } } // End if horizontal scroll bar needed else { if ( hsbOn && !hsbAlwaysOn ) { XtVaSetValues(hlForm, XmNbottomOffset, noScrollBoff, NULL); drawHt += sbSize; hsbOn = False; } } // End if horizontal scroll bar not needed hsbMax = MAX((int)drawWd, textWd); ss = MIN((int)drawWd, hsbMax); if ( hsbVal + ss > hsbMax ) hsbVal = hsbMax - ss; pi = drawWd - pub->CharWidth(); if ( pi <= 0 ) pi = drawWd; args.Value(hsbVal); args.Maximum(hsbMax); args.MappedWhenManaged(hsbOn); args.SliderSize(ss); args.PageIncrement(pi); XtSetValues(textHSB, ARGS); CheckPixmapSize(); } // End if we didn't already do this } // End if we're doing our own scroll bars} // End PlaceLines/*---------------------------------------------------------------------- * Format the text lines */voidMimeRichTextP::FormatScreen(){ if ( defer || !changed || !realized ) return; if ( debuglev > 1 ) cout <<"MimeRichTextC(" <<XtName(pub->MainWidget()) <<")::FormatScreen" <<endl; textWd = marginWd2; textHt = marginHt2;//// Remove all soft lines// TextLineC *tline = topTextLine; while ( tline ) { SoftLineC *sline = tline->softLine; while ( sline && sline->textLine == tline ) { SoftLineC *next = sline->next; delete sline; sline = next; } tline->softLine = NULL; tline = tline->next; } topSoftLine = botSoftLine = NULL;//// Process the lines and link soft lines as we go// tline = topTextLine; while ( tline ) { FormatLine(tline); if ( !topSoftLine ) { topSoftLine = tline->FirstSoft(); botSoftLine = tline->LastSoft(); } else { SoftLineC *first = tline->FirstSoft(); botSoftLine->next = first; first->prev = botSoftLine; botSoftLine = tline->LastSoft(); } tline = tline->next; }//// Set the text width to the maximum line width and justify all lines.// textWd = MaxLineWidth(); JustifyLines(); // Set horizontal positions//// Set the lines' vertical positions// PlaceLines(); pub->ResetPartIndex(); changed = False; if ( debuglev > 1 ) cout <<"Leaving FormatScreen" NL;} // End FormatScreen/*---------------------------------------------------------------------- * Lay out the specified text line */voidMimeRichTextP::FormatLine(TextLineC *textLine){ if ( debuglev > 1 ) cout <<"Formatting line " <<textLine->index <<endl;//// Delete the soft lines for this text// SoftLineC *sline = textLine->softLine; while ( sline && sline->textLine == textLine ) { SoftLineC *next = sline->next; delete sline; sline = next; } textLine->softLine = NULL;// If we do this, we can't change state at the end of some text#if 0//// Make the line as efficient as possible// CompactLine(textLine);#endif//// Create a new soft line// SoftLineC *softLine = new SoftLineC; softLine->textLine = textLine; textLine->softLine = softLine;//// Get the initial state and the initial indent conditions// TextStateC *state = textLine->State(0); int lindent = state->LIndent(); int rindent = state->RIndent();//// Determine the available width// int availWd; if ( resizeWidth ) availWd = 32768; else availWd = drawWd - (indentWd * (lindent + rindent)) - (excerptWd * state->Excerpt()) - marginWd2; int leftX = marginWd + (state->Excerpt() * excerptWd) + (lindent * indentWd);//// Loop through the commands.// unsigned ccount = textLine->cmdList.size(); RichCmdC *cmd; int i=0; for (i=0; i<ccount; i++) { cmd = textLine->Cmd(i); if ( cmd->IsText() ) softLine = FormatText(textLine, softLine, i, cmd->state, &leftX, &availWd, &lindent, &rindent); else softLine = FormatGraphic(textLine, softLine, i, cmd->state, &leftX, &availWd, &lindent, &rindent); } // End for each command//// If there is a blank soft line at the end of the list, remove it. If it// is the only one, leave it.// SoftLineC *first = textLine->FirstSoft(); SoftLineC *last = textLine->LastSoft(); if ( first != last && !last->drawData ) { last->prev->next = NULL; delete softLine; }//// Loop through the soft lines and calculate their sizes// leftX = marginWd + (state->Excerpt() * excerptWd) + (lindent * indentWd); int textLineHt = 0; int textLineWd = 0; RichDrawDataC *prevData = NULL; sline = textLine->softLine; while ( sline && sline->textLine == textLine ) {//// Create an empty draw data for any soft line that has none// if ( !sline->drawData ) { RichDrawDataC *data = new RichDrawDataC; data->softLine = sline; if ( prevData ) { data->cmdPos = prevData->cmdPos; data->textOff = prevData->textOff + prevData->string.size(); data->font = prevData->font; data->underline = prevData->underline; } else { data->cmdPos = 0; data->textOff = 0; data->font = CurFont(*state); data->underline = (state->Underline()>0); } data->x = leftX; data->width = 0; RichDrawDataC *lastData = softLine->LastData(); if ( lastData ) { lastData->next = data; data->prev = lastData; } else { softLine->drawData = data; } } // End if this is an empty line else { prevData = sline->LastData(); }//// Calculate width and height// GetLineSize(sline);//// Update the bounds of this text line// textLineHt += sline->bounds.ht; textLineHt += lineSpacing; if ( /*resizeWidth &&*/ sline->totalWd > textLineWd ) textLineWd = sline->totalWd; sline = sline->next; } // End for each soft line textLineHt -= lineSpacing; if ( textLineHt == 0 ) textLineHt = 1; textLine->bounds.SetSize(textLineWd, textLineHt); if ( debuglev > 1 ) cout <<"Text Line bounds are: " <<textLine->bounds.xmin <<" " <<textLine->bounds.ymin <<" " <<textLine->bounds.wd <<" " <<textLine->bounds.ht <<endl;//// Position the soft lines vertically// SetLinePosition(textLine, textLine->bounds.ymin);} // End FormatLine/*---------------------------------------------------------------------- * Try to place the text in the available area. Wrap if necessary */SoftLineC*MimeRichTextP::FormatText(TextLineC *textLine, SoftLineC *softLine, int cmdPos, TextStateC& state, int *leftX, int *availWd, int *lindent, int *rindent){//// Grab the text// StringC *textStr = textLine->Text(cmdPos); char *cs = *textStr; int len = textStr->size(); int remaining = len; if ( debuglev > 1 ) cout <<"Formatting text ^" <<*textStr <<"^" <<endl;//// If the length is 0, create one draw data and be done with it// if ( remaining == 0 ) { RichDrawDataC *data = new RichDrawDataC; data->softLine = softLine; data->cmdPos = cmdPos; data->textOff = 0; data->x = *leftX; data->width = 0; data->font = CurFont(state); data->underline = (state.Underline()>0); data->string = ""; softLine->AddDrawData(data); }//// Loop until we're fininshed with this text// while ( remaining > 0 ) {//// If there are any tabs, split them out// char *tp = strchr(cs, '\t'); if ( tp ) { if ( tp == cs ) len = 1; else len = tp - cs; }//// Get size of text// int dir, asc, dsc; XCharStruct size; FontDataC *curFont = CurFont(state); if ( *cs == '\t' ) { int charWd = curFont->CharWidth(); int tabSize = tabStop * charWd; int tabX = (state.Excerpt() * excerptWd) + (state.LIndent() * indentWd) + tabSize; while ( tabX <= *leftX ) tabX += tabSize; size.width = tabX - *leftX; } else { XTextExtents(curFont->xfont, cs, len, &dir, &asc, &dsc, &size); }//// If it doesn't fit, find out how much will// Boolean addIt = True; Boolean lineFull = (size.width > *availWd); if ( lineFull ) { if ( *cs == '\t' ) { addIt = (softLine->drawData == NULL); } else { int fitLen = FitText(cs, curFont->xfont, *availWd); if ( fitLen > 0 ) { len = fitLen; XTextExtents(curFont->xfont, cs, len, &dir, &asc, &dsc, &size); } else addIt = (softLine->drawData == NULL); } }//// Add this section of text if necessary// if ( addIt ) {//// Create a new draw data// RichDrawDataC *data = new RichDrawDataC; data->softLine = softLine; data->cmdPos = cmdPos; data->textOff = cs - (char*)*textStr; data->x = *leftX; data->width = size.width; data->font = curFont; data->underline = (state.Underline()>0); data->string.Set(cs, len); softLine->AddDrawData(data);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -