📄 mimerichtextdraw.c
字号:
/* * $Id: MimeRichTextDraw.C,v 1.2 2000/05/07 12:26:10 fnevgeny Exp $ * * Copyright (c) 1994 HAL Computer Systems International, Ltd. * * HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. * 1315 Dell Avenue * Campbell, CA 95008 * * Author: Greg Hilton * Contributors: Tom Lang, Frank Bieser, and others * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * http://www.gnu.org/copyleft/gpl.html * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <config.h>#include "MimeRichTextC.h"#include "MimeRichTextP.h"#include "HalAppC.h"#include "WArgList.h"#include "gray.xbm"#include <Xm/ScrollBar.h>extern int debuglev;/*---------------------------------------------------------------------- * Expose Callback */voidMimeRichTextP::HandleExpose(Widget, MimeRichTextP *This, XmDrawingAreaCallbackStruct *da){ if ( !This->realized ) { This->textWin = XtWindow(This->textDA);//// Create stipple pixmap// This->stipplePm = XCreateBitmapFromData(halApp->display, This->textWin, gray_bits, gray_width, gray_height); Window root; int x, y; unsigned w, h; unsigned bw; unsigned dep; XGetGeometry(halApp->display, This->stipplePm, &root, &x, &y, &w, &h, &bw, &dep);//// Create graphics contexts for drawing// XtGCMask fixMask = GCGraphicsExposures | GCBackground | GCLineStyle | GCLineWidth | GCPlaneMask | GCStipple; XtGCMask modMask = GCClipMask | GCFont | GCFunction | GCForeground | GCFillStyle; XtGCMask naMask = GCArcMode | GCCapStyle | GCClipXOrigin | GCClipYOrigin | GCDashList | GCDashOffset | GCFillRule | GCJoinStyle | GCSubwindowMode | GCTile | GCTileStipXOrigin | GCTileStipYOrigin; XGCValues fixVals; fixVals.clip_mask = None; fixVals.fill_style = FillSolid; fixVals.stipple = This->stipplePm; fixVals.font = This->plainFont.fid; fixVals.foreground = This->fgColor; fixVals.background = This->bgColor; fixVals.function = GXcopy; fixVals.graphics_exposures = TRUE; fixVals.line_style = LineSolid; fixVals.line_width = 0; fixVals.plane_mask = AllPlanes; This->textGC = XtAllocateGC(This->textDA, 0, fixMask, &fixVals, modMask, naMask); This->cursorPos.Set(This->topTextLine, 0, 0); ScreenPosC spos = This->cursorPos; This->desiredCursorX = spos.x; This->cursorOn = False;//// Get scrollbars if necessary// if ( This->textSW ) { XtVaGetValues(This->textSW, XmNverticalScrollBar, &This->textVSB, XmNhorizontalScrollBar, &This->textHSB, XmNclipWindow, &This->textClip, NULL); XtVaGetValues(This->textClip, XmNwidth, &This->clipWd, XmNheight, &This->clipHt, NULL); if ( This->drawWd == 0 ) XtVaGetValues(This->textDA, XmNwidth, &This->drawWd, NULL); if ( This->drawHt == 0 ) XtVaGetValues(This->textDA, XmNwidth, &This->drawHt, NULL); This->maxWd = This->drawWd; This->maxHt = This->drawHt;//// If resize is not allowed, keep the text the same width as the scrolled// window// if ( !This->resizeWidth ) XtAddEventHandler(This->textSW, StructureNotifyMask, False, (XtEventHandler)HandleSWResize, (XtPointer)This); } // End if we're in a scrolled window else { if ( (int)This->drawWd <= (int)(This->marginWd*2) ) XtVaGetValues(This->textDA, XmNwidth, &This->drawWd, NULL); if ( (int)This->drawHt <= (int)(This->marginHt*2) ) XtVaGetValues(This->textDA, XmNheight, &This->drawHt, NULL); This->maxWd = This->drawWd; This->maxHt = This->drawHt;//// Set scrollbar values// WArgList args; args.Minimum(0); args.Value(0); int lh = This->pub->LineHeight(); args.Increment(lh); if ( (int)This->drawHt > lh ) { args.Maximum(This->drawHt); args.SliderSize(This->drawHt); args.PageIncrement(This->drawHt - lh); } XtSetValues(This->textVSB, ARGS); int cw = This->pub->CharWidth(); args.Increment(cw); if ( (int)This->drawWd > cw ) { args.Maximum(This->drawWd); args.SliderSize(This->drawWd); args.PageIncrement(This->drawWd - cw); } XtSetValues(This->textHSB, ARGS); This->hsbVal = This->vsbVal = 0; This->hsbMax = This->drawWd; This->vsbMax = This->drawHt;//// Create a pixmap for off-screen drawing// unsigned depth = DefaultDepth(halApp->display, DefaultScreen(halApp->display)); This->textPmWd = This->drawWd; This->textPmHt = This->drawHt; This->textPm = XCreatePixmap(halApp->display, This->textWin, This->textPmWd, This->textPmHt, depth); XtAddEventHandler(This->scrollForm, StructureNotifyMask, False, (XtEventHandler)HandleFormResize, (XtPointer)This); } // End if we're doing our own scrolling This->realized = True; This->FormatScreen();//// Initialize the input method// if ( This->editable ) { XmImRegister(This->textDA, 0); XPoint spot; spot.x = 0; spot.y = 0; Pixmap bgPixmap; XtVaGetValues(This->textDA, XmNbackgroundPixmap, &bgPixmap, NULL); XmFontList fontList = XmFontListCreate(This->plainFont.xfont, XmSTRING_DEFAULT_CHARSET); WArgList args; args.Background(This->bgColor); args.Foreground(This->fgColor); args.BackgroundPixmap(bgPixmap); args.FontList(fontList); args.Add("XmNlineSpacing", This->lineSpacing); args.Add("XmNspotLocation", &spot); XmImSetValues(This->textDA, ARGS); } // End if input method needed//// Start the cursor blinking if the focus is here// if ( This->hasFocus ) CursorBlink(This, NULL); } // End if not realized//// Redraw// XExposeEvent *ev = (XExposeEvent*)da->event; RectC area(ev->x, ev->y, ev->width, ev->height); This->DrawScreen(area);} // End HandleExpose/*---------------------------------------------------------------------- * Resize callback for scrollForm */voidMimeRichTextP::HandleFormResize(Widget, MimeRichTextP *This, XEvent*, Boolean*){ if ( debuglev > 1 ) cout <<"MimeRichTextC(" <<XtName(This->pub->MainWidget()) <<")::HandleFormResize" <<endl; Dimension wd, ht; XtVaGetValues(This->textDA, XmNwidth, &wd, XmNheight, &ht, NULL); if ( wd == This->drawWd && ht == This->drawHt ) return; halApp->BusyCursor(True);//// See how much the size changed. Change the max size by these same amounts.// Dimension dwd = wd - This->drawWd; Dimension dht = ht - This->drawHt; This->drawWd = wd; This->drawHt = ht; This->maxWd += dwd; This->maxHt += dht; This->CheckPixmapSize();//// Update drawing area// This->changed = True; This->FormatScreen(); if ( This->realized ) { RectC area(0, 0, wd, ht); This->DrawScreen(area); ScreenPosC spos = This->cursorPos; This->desiredCursorX = spos.x; } halApp->BusyCursor(False);} // End HandleResize/*----------------------------------------------------------------------- * Event handler for scrolled window resize */voidMimeRichTextP::HandleSWResize(Widget, MimeRichTextP *This, XEvent*, Boolean*){//// Get the size of the clip window// XtVaGetValues(This->textClip, XmNwidth, &This->clipWd, XmNheight, &This->clipHt, NULL);//// If we're not allowed to resize ourself, follow the size of the scrolled// window.// if ( !This->resizeWidth ) { halApp->BusyCursor(True); Dimension wd = This->clipWd - 1; XtVaSetValues(This->textDA, XmNwidth, wd, NULL); This->drawWd = wd; This->changed = True; This->FormatScreen(); if ( This->realized ) { RectC area(0, 0, This->drawWd, This->drawHt); This->DrawScreen(area); ScreenPosC spos = This->cursorPos; This->desiredCursorX = spos.x; } halApp->BusyCursor(False); } // End if we're not allowed to set our own size} // End HandleSWResize/*---------------------------------------------------------------------- * Adjust the reference widget so the specified amount of the drawing * area size is displayed. */voidMimeRichTextP::SetVisibleSize(Dimension newWd, Dimension newHt, Widget ref){//// If we're in a scrolled window, resize that// if ( textSW ) { if ( !ref ) ref = textSW;//// Get the current size// Dimension swd, sht; XtVaGetValues(ref, XmNwidth, &swd, XmNheight, &sht, NULL);//// Determine the size difference// Dimension dwd = swd - clipWd; Dimension dht = sht - clipHt;//// Calculate the new size needed for the scrolled window// clipWd = newWd + marginWd2 + 1; clipHt = newHt + marginHt2 + 1; swd = clipWd + dwd; sht = clipHt + dht; XtVaSetValues(ref, XmNwidth, swd, XmNheight, sht, NULL); //// Calculate the new size needed for the text form// Dimension fwd = newWd + marginWd2; Dimension fht = newHt + marginHt2; if ( resizeWidth || (int)fwd < (int)(clipWd - 1) ) fwd = clipWd - 1; if ( (int)fht < (int)(clipHt - 1) ) fht = clipHt - 1; XtVaSetValues(textDA, XmNwidth, fwd, XmNheight, fht, NULL);//// Remove any resize events from the queue. We don't need them.// XSync(halApp->display, FALSE); XEvent event; while ( XCheckTypedWindowEvent(halApp->display, XtWindow(textSW), ConfigureNotify, &event) ) ; } // End if we're in a scrolled window//// If we're doing our own scrolling, resize the scrollForm// else {//// Get the current size// Dimension swd = 0, sht = 0; if ( ref ) XtVaGetValues(ref, XmNwidth, &swd, XmNheight, &sht, NULL); if ( swd > 0 && sht > 0 ) {//// Determine the size difference// Dimension dwd = swd - drawWd; Dimension dht = sht - drawHt;//// Set the new size// swd = newWd + dwd; sht = newHt + dht; XtVaSetValues(ref, XmNwidth, swd, XmNheight, sht, NULL); } // End if reference widget is specified//// Compute the size of the scrollForm required to give us the requested// drawing area size// else { Dimension shad; XtVaGetValues(textFrame, XmNshadowThickness, &shad, NULL); swd = newWd + shad // textFrame + (hlThick*2) // hlForm + 2; // for grins if ( vsbOn ) swd += scrollRoff; else swd += noScrollRoff; sht = newHt + shad // textFrame + (hlThick*2) // hlForm + 2; // for grins if ( hsbOn ) sht += scrollBoff; else sht += noScrollBoff; XtVaSetValues(scrollForm, XmNwidth, swd, XmNheight, sht, NULL); } // End if no reference widget is specified#if 0//// Remove any resize events from the queue. We don't need them.// XSync(halApp->display, FALSE); XEvent event; while ( XCheckTypedWindowEvent(halApp->display, XtWindow(scrollForm), ConfigureNotify, &event) ) ;#endif } // End if we're doing our own scrolling maxWd = drawWd = newWd; maxHt = drawHt = newHt;//// Reallocate pixmap// CheckPixmapSize();//// Update drawing area// changed = True; if ( !defer ) { FormatScreen(); if ( realized ) { RectC area(0, 0, maxWd, maxHt); DrawScreen(area); ScreenPosC spos = cursorPos; desiredCursorX = spos.x; } }} // End SetVisibleSize/*----------------------------------------------------------------------- * Resize the off-screen pixmap if the visible area has increased */voidMimeRichTextP::CheckPixmapSize(){//// Re-create pixmap if size has increased// if ( !textPm || (drawWd <= textPmWd && drawHt <= textPmHt) ) return; XFreePixmap(halApp->display, textPm); u_int depth = DefaultDepth(halApp->display, DefaultScreen(halApp->display)); textPmWd = MAX(drawWd, textPmWd); textPmHt = MAX(drawHt, textPmHt); textPm = XCreatePixmap(halApp->display, textWin, textPmWd, textPmHt, depth);} // End CheckPixmapSize/*----------------------------------------------------------------------- * Format the specified line and redraw all affected lines */voidMimeRichTextP::LineChanged(TextLineC *tline, Boolean forcePlace){ LinesChanged(tline, tline, forcePlace);}/*----------------------------------------------------------------------- * Format the specified lines and redraw all affected lines */voidMimeRichTextP::LinesChanged(TextLineC *begLine, TextLineC *endLine, Boolean forcePlace){//// Re-format the text lines// Boolean placeNeeded = False; Boolean widthNeeded = False; Boolean widthChanged = False; TextLineC *tline = begLine; SoftLineC *sprev = begLine->prev ? begLine->prev->LastSoft() : (SoftLineC*)NULL; while ( tline != endLine->next ) { int oldHt = tline->bounds.ht; int oldWd = tline->bounds.wd; FormatLine(tline); if ( !placeNeeded ) placeNeeded = (oldHt != tline->bounds.ht);//// If the line shrunk, we'll have to recalculate the max line width for all// lines.// if ( tline->bounds.wd < oldWd ) widthNeeded = True;//// If the line grew, see if the text width is affected. If it is, we'll have// to re-justify all lines.// else if ( tline->bounds.wd > textWd ) { textWd = tline->bounds.wd; widthChanged = True; }//// Update the soft line links// SoftLineC *first = tline->FirstSoft(); if ( sprev ) { sprev->next = first; first->prev = sprev; } else topSoftLine = first; sprev = tline->LastSoft(); tline = tline->next; } // End for each changed line//// Update last soft link// SoftLineC *snext = endLine->next ? endLine->next->FirstSoft() : (SoftLineC*)NULL; SoftLineC *last = endLine->LastSoft(); if ( snext ) { last->next = snext; snext->prev = last; } else botSoftLine = last;//// See if we need to recalculate the maximum line width.// if ( widthNeeded ) { int newWd = MaxLineWidth(); if ( newWd != textWd ) { textWd = newWd; widthChanged = True; } }//// If the max width has changed, we'll need to re-justify all lines.// If not, we'll justify only the lines that changed// if ( widthChanged ) JustifyLines(); else /*if ( resizeWidth )*/ { tline = begLine; while ( tline != endLine->next ) { SoftLineC *sline = tline->softLine; while ( sline && sline->textLine == tline ) { Justify(sline); sline = sline->next; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -