📄 mimerichtextdraw.c
字号:
*availWd -= size.width; *leftX += size.width;//// Advance past this text// remaining -= len; cs += len; len = remaining; } // End if block added to current line//// Start a new line if it didn't all fit// if ( lineFull ) {//// Create a new soft line// softLine = new SoftLineC; softLine->textLine = textLine; textLine->AddSoftLine(softLine);//// Update the indention// *lindent = state.LIndent(); *rindent = state.RIndent();//// Compute the new available width// if ( resizeWidth ) *availWd = 32768; else *availWd = drawWd - (indentWd * (*lindent + *rindent)) - (excerptWd * state.Excerpt()) - marginWd2; *leftX = marginWd + (state.Excerpt() * excerptWd) + (*lindent * indentWd);//// Skip whitespace except tabs// if ( len == 0 ) len = remaining; while ( remaining > 0 && isspace(*cs) && *cs != '\t' ) { cs++; remaining--; len--; } } // End if more characters remain } // End while more characters remain return softLine;} // End FormatText/*---------------------------------------------------------------------- * See how many characters will fit in the available width. */intMimeRichTextP::FitText(char *cp, XFontStruct *font, int availWd){ int wd = 0; char *wp = cp; int len = 0;//// Loop while we have more room and more characters// while ( *wp && availWd > wd ) {//// Skip over current whitespace// while ( *wp && isspace(*wp) ) wp++;//// Look for next whitespace// while ( *wp && !isspace(*wp) ) wp++;//// See how long this section is// int wlen = wp - cp; int dir, asc, dsc; XCharStruct size; XTextExtents(font, cp, wlen, &dir, &asc, &dsc, &size); wd = size.width; if ( wd <= availWd ) len = wlen; } // End while more room and more chars return len;} // End FitText/*---------------------------------------------------------------------- * Try to place the graphic in the available area. Wrap if necessary */SoftLineC*MimeRichTextP::FormatGraphic(TextLineC *textLine, SoftLineC *softLine, int cmdPos, TextStateC& state, int *leftX, int *availWd, int *lindent, int *rindent){ RichGraphicC *rg = textLine->Graphic(cmdPos); if ( debuglev > 1 ) cout <<"Formatting graphic ^" <<rg <<"^" <<endl; int prefWd = rg->PrefWidth(); int prefHt = rg->PrefHeight();//// Start a new line if the current line is full.// if ( prefWd > *availWd && softLine->drawData != NULL ) {//// Create a new soft line// softLine = new SoftLineC; softLine->textLine = textLine; textLine->AddSoftLine(softLine);//// Update the indention// *lindent = state.LIndent(); *rindent = state.RIndent();//// Compute the new available width// if ( resizeWidth ) *availWd = 32768; else *availWd = drawWd - (indentWd * (*lindent + *rindent)) - (excerptWd * state.Excerpt()) - marginWd2; *leftX = marginWd + (state.Excerpt() * excerptWd) + (*lindent * indentWd); } // End if graphic won't fit//// Now add the graphic. First, create a new draw data// RichDrawDataC *data = new RichDrawDataC; data->softLine = softLine; data->cmdPos = cmdPos; data->x = *leftX; data->width = prefWd; data->graphic = rg; rg->bounds.Set(*leftX, textLine->bounds.ymin, prefWd, prefHt); if ( debuglev > 1 ) cout <<" bounds are " <<rg->bounds.xmin SP rg->bounds.ymin SP rg->bounds.wd SP rg->bounds.ht <<endl; softLine->AddDrawData(data);//// Update the available space.// *availWd -= prefWd; *leftX += prefWd; return softLine;} // End FormatGraphic/*---------------------------------------------------------------------- * Get the width and height of a soft line */voidMimeRichTextP::GetLineSize(SoftLineC *line){ int lineWd = 0; int lineHt = 0; line->descent = 0; TextStateC *state = NULL; RichDrawDataC *dd = line->drawData; while ( dd ) {//// Update width// lineWd += dd->width;//// Update height// if ( dd->graphic ) { if ( dd->graphic->bounds.ht > lineHt ) lineHt = dd->graphic->bounds.ht; } else { int fontHt = dd->font->xfont->ascent + dd->font->xfont->descent; if ( fontHt > lineHt ) lineHt = fontHt; if ( dd->font->xfont->descent > line->descent ) line->descent = dd->font->xfont->descent; }//// Save initial state for use below// if ( dd == line->drawData && line->textLine ) state = line->textLine->State(dd->cmdPos); dd = dd->next; } // End for each draw data//// Add size of excerpt string if necessary// if ( state && state->Excerpt() ) { int fontHt = plainFont.xfont->ascent + plainFont.xfont->descent; if ( fontHt > lineHt ) lineHt = fontHt; if ( plainFont.xfont->descent > line->descent ) line->descent = plainFont.xfont->descent; }//// Fall back to default font height if line is blank// if ( lineHt == 0 ) { lineHt = plainFont.xfont->ascent + plainFont.xfont->descent; line->descent = plainFont.xfont->descent; } line->bounds.SetSize(lineWd, lineHt);//// See what indentation and excerpting does to the width// line->totalWd = lineWd; if ( state ) { line->totalWd += indentWd * (state->LIndent() + state->RIndent()); line->totalWd += excerptWd * state->Excerpt(); } line->totalWd += marginWd2;} // End GetLineSize/*---------------------------------------------------------------------- * Justify all soft lines */voidMimeRichTextP::JustifyLines(){ SoftLineC *line = topSoftLine; while ( line ) { Justify(line); line = line->next; }}/*---------------------------------------------------------------------- * Justify the specified line */voidMimeRichTextP::Justify(SoftLineC *line){//// Get the state for the first draw data// TextStateC *state = NULL; if ( line->drawData && line->textLine ) { RichDrawDataC *dd = line->drawData; state = line->textLine->State(dd->cmdPos); }//// Calculate left and right edges// int lx = marginWd + (state->Excerpt() * excerptWd) + (state->LIndent() * indentWd); int rx; if ( resizeWidth ) rx = MAX(textWd, (int)drawWd); else rx = drawWd; rx -= marginWd + (state->RIndent() * indentWd);//// Center if necessary// int lineX = lx; if ( state->CurJustCmd() == JC_CENTER ) { int avail = rx - lx + 1; int pad = (avail - line->bounds.wd) / (int)2; lineX = lx + pad; } else if ( state->CurJustCmd() == JC_RIGHT ) { lineX = rx - line->bounds.wd; } if ( lineX < lx ) lineX = lx; line->bounds.SetPos(lineX, line->bounds.ymin);//// Adjust data segments// RichDrawDataC *dd = line->drawData; while ( dd ) { dd->x = lineX; if ( dd->graphic ) dd->graphic->bounds.SetPos(lineX, dd->graphic->bounds.ymin); lineX += dd->width; dd = dd->next; }} // End Justify/*---------------------------------------------------------------------- * Return the maximum soft line width */intMimeRichTextP::MaxLineWidth(){ int maxWd = 0; SoftLineC *line = topSoftLine; while ( line ) { if ( line->totalWd > maxWd ) maxWd = line->totalWd; line = line->next; } return maxWd;}/*-------------------------------------------------------------------- * Method to set the Y position for a line */voidMimeRichTextP::SetLinePosition(TextLineC *textLine, int y){ textLine->bounds.SetPos(textLine->bounds.xmin, y);//// Update the soft lines// SoftLineC *sline = textLine->softLine; while ( sline && sline->textLine == textLine ) { sline->bounds.SetPos(sline->bounds.xmin, y); RichDrawDataC *dd = sline->drawData; while ( dd ) { if ( dd->graphic ) { dd->graphic->bounds.ymax = sline->bounds.ymax; dd->graphic->bounds.ymin = sline->bounds.ymax - dd->graphic->bounds.ht + 1; } dd = dd->next; } // End for each draw data y += sline->bounds.ht + lineSpacing; sline = sline->next; } // End for each soft line} // End SetLinePosition/*---------------------------------------------------------------------- * Redraw the lines in the specified range */voidMimeRichTextP::DrawLines(SoftLineC *begLine, SoftLineC *endLine){ if ( !realized || defer ) return; int ht = endLine->bounds.ymax - begLine->bounds.ymin + 1; Drawable drawto = pub->DrawTo(); RectC visArea(hsbVal, vsbVal, drawWd, drawHt);//// Clear the drawing area// XSetForeground(halApp->display, textGC, bgColor); XFillRectangle(halApp->display, drawto, textGC, 0, begLine->bounds.ymin-vsbVal, drawWd, ht); XSetForeground(halApp->display, textGC, fgColor);//// Draw each line// long lastFont = 0; Pixel lastColor = fgColor; SoftLineC *line = begLine; Boolean done = False; while ( !done ) { if ( visArea.OverlapsY(line->bounds) ) DrawLine(line, &lastFont, &lastColor); else HideLineGraphics(line); done = (line == endLine); line = line->next; } if ( drawto != textWin ) XCopyArea(halApp->display, drawto, textWin, textGC, 0, 0, drawWd, drawHt, 0, 0);} // End DrawLines/*---------------------------------------------------------------------- * Draw the current text. The specified area is in textDA coordinates. */voidMimeRichTextP::DrawScreen(RectC& area){ if ( !realized || defer ) return; if ( debuglev > 1 ) cout <<"MimeRichTextC(" <<XtName(pub->MainWidget()) <<")::DrawScreen with area: " <<area.xmin <<" " <<area.ymin <<" " <<area.wd <<" " <<area.ht <<endl; Drawable drawto = pub->DrawTo(); RectC visArea(0, 0, drawWd, drawHt); if ( !area.Overlaps(visArea) ) return;//// Intersect the area to be drawn with the visible area// RectC drawArea = area | visArea; HideCursor();//// Update the size of the drawing area// if ( textSW ) { if ( resizeWidth ) { if ( debuglev > 1 ) cout <<"setting width to " <<drawWd NL; XtVaSetValues(textDA, XmNwidth, drawWd+marginWd2, 0); } else if ( drawWd != clipWd - marginWd2 - 1 ) { drawWd = clipWd - marginWd2 - 1; if ( debuglev > 1 ) cout <<"setting width to " <<drawWd NL; XtVaSetValues(textDA, XmNwidth, drawWd+marginWd2, 0); } if ( debuglev > 1 ) cout <<"setting height to " <<drawHt NL; XtVaSetValues(textDA, XmNheight, drawHt+marginHt2, 0); } XRectangle rect; rect.x = (short)drawArea.xmin; rect.y = (short)drawArea.ymin; rect.width = (short)drawArea.wd; rect.height = (short)drawArea.ht; XSetClipRectangles(halApp->display, textGC, 0, 0, &rect, 1, YXBanded);//// Clear the drawing area// XSetForeground(halApp->display, textGC, bgColor); XFillRectangle(halApp->display, drawto, textGC, drawArea.xmin, drawArea.ymin, drawArea.wd, drawArea.ht); XSetForeground(halApp->display, textGC, fgColor);//// Gray out the data if we're not sensitive// if ( !XtIsSensitive(textDA) ) XSetFillStyle(halApp->display, textGC, FillStippled);//// Scroll the area if we're doing our own scrolling// RectC sarea(drawArea); sarea.xmin += hsbVal; sarea.xmax += hsbVal; sarea.ymin += vsbVal; sarea.ymax += vsbVal; visArea.xmin += hsbVal; visArea.xmax += hsbVal; visArea.ymin += vsbVal; visArea.ymax += vsbVal;//// Loop through the lines// long lastFont = 0; Pixel lastColor = fgColor; SoftLineC *line = topSoftLine; while ( line ) { if ( debuglev > 1 ) cout <<"Checking soft line: " <<line->bounds.xmin <<" " <<line->bounds.ymin <<" " <<line->bounds.wd <<" " <<line->bounds.ht <<endl;//// Draw line if it is visible// if ( sarea.OverlapsY(line->bounds) ) DrawLine(line, &lastFont, &lastColor); else if ( !visArea.OverlapsY(line->bounds) ) HideLineGraphics(line); line = line->next; } // End for each line//// Gray out the data if we're not sensitive// if ( !XtIsSensitive(textDA) ) XSetFillStyle(halApp->display, textGC, FillSolid);//// Refresh selection// if ( selectOn ) DrawSelection(); // This will also call XCopyArea else if ( drawto != textWin ) XCopyArea(halApp->display, drawto, textWin, textGC, 0, 0, drawWd, drawHt, 0, 0); XSetClipMask(halApp->display, textGC, None); ShowCursor();} // End DrawScreen/*---------------------------------------------------------------------- * Draw the specified line */voidMimeRichTextP::DrawLine(SoftLineC *line, long *lastFont, Pixel *lastColor, Boolean clear){ if ( !realized || defer ) return; Drawable drawto = pub->DrawTo(); if ( debuglev > 1 ) cout <<"Drawing line with bounds: " <<line->bounds.xmin <<" " <<line->bounds.ymin <<" " <<line->bounds.wd <<" " <<line->bounds.ht <<endl; if ( clear ) {//// Clear the line area// XSetForeground(halApp->display, textGC, bgColor); XFillRectangle(halApp->display, drawto, textGC, 0, line->bounds.ymin-vsbVal, drawWd, line->bounds.ht); XSetForeground(halApp->display, textGC, fgColor); } int lineX = line->bounds.xmin; int botY = line->bounds.ymax;//// Draw excerpt string if necessary// TextStateC *state = line->textLine->State(0); if ( state->Excerpt() ) { int x = marginWd; int y = botY - line->descent; if ( *lastFont != plainFont.fid ) { XSetFont(halApp->display, textGC, plainFont.fid); *lastFont = plainFont.fid; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -