📄 mimerichtextselect.c
字号:
/* * $Id: MimeRichTextSelect.C,v 1.4 2000/12/25 15:05:52 evgeny 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 "rsrc.h"#include "System.h"#include "CharC.h"#include <Xm/AtomMgr.h>#include <Xm/CutPaste.h>#include <X11/Xatom.h>#include <X11/Xmu/Atoms.h>#include <X11/Xmu/StdSel.h>#include <X11/Xmu/CharSet.h>#include <X11/IntrinsicP.h>#include <X11/CoreP.h>#include <math.h>#include <values.h> // For MAXINTextern int debuglev;/*---------------------------------------------------------------------- * Callback to handle loss of primary selection ownership */voidMimeRichTextP::LoseSelection(Widget w, Atom*){ MimeRichTextC *This; XtVaGetValues(w, XmNuserData, &This, NULL);//// Clear current selection since we no longer own it.// if ( This->priv->selectOn ) This->priv->DrawSelection(); This->priv->selectOn = False;}/*---------------------------------------------------------------------- * Callback to handle request for primary selection */BooleanMimeRichTextP::SendSelection(Widget w, Atom *selection, Atom *target, Atom *type, XtPointer *val, unsigned long *len, int *format){ MimeRichTextC *This; XtVaGetValues(w, XmNuserData, &This, NULL);//// Handle required atoms// if ( *target == XA_TARGETS(halApp->display) ) { *len = 4; *val = XtMalloc((Cardinal)(sizeof(Atom) * (*len))); Atom *targetP = *(Atom**)val; *targetP++ = XA_STRING; *targetP++ = XA_TEXT(halApp->display); *targetP++ = XA_COMPOUND_TEXT(halApp->display); *targetP++ = mimeRichAtom; *type = XA_ATOM; *format = sizeof(Atom) * 8; return True; } // End if someone wants to know what types we can send else if ( *target != XA_STRING && *target != XA_TEXT(halApp->display) && *target != XA_COMPOUND_TEXT(halApp->display) && *target != mimeRichAtom ) { return XmuConvertStandardSelection(w, CurrentTime, selection, target, type, (caddr_t*)val, len, format); }//// Now handle the targets we can supply// if ( *target == XA_TEXT(halApp->display) ) *type = XA_STRING; else *type = *target; *format = sizeof(char) * 8;//// If there's a current selection, try that// if ( This->priv->selectOn ) {//// Load up the output// StringC outbuf; This->priv->GetSelectionData(outbuf, (*target == mimeRichAtom) ? TT_ENRICHED : TT_PLAIN);//// Get the length of the selection// *len = outbuf.size();//// Allocate memory for selection data. This memory will be freed by the// Intrinsics since we didn't register an XtSelectionDoneProc// *val = XtMalloc((Cardinal)*len);//// Copy current selection// register char *dst = (char*)(*val); register char *src = (char*)outbuf; for (int i=0; i<*len; i++) *dst++ = *src++; } // End if there's a current selection//// Try the clipboard if there's no selection// else { int status; u_long clipLen; Window win = XtWindow(This->priv->textDA); char *format = (char *) ((*target == mimeRichAtom) ? MIME_ENRICHED_ATOM_NAME : "STRING"); do { status = XmClipboardInquireLength(halApp->display, win, format, &clipLen); } while ( status == ClipboardLocked ); if ( clipLen == 0 || status == ClipboardNoData ) return False;//// Allocate memory for selection data. This memory will be freed by the// Intrinsics since we didn't register an XtSelectionDoneProc// *val = XtMalloc((Cardinal)clipLen+1); char *out = (char*)*val; long privId; do { status = XmClipboardRetrieve(halApp->display, win, format, out, clipLen, len, &privId); } while ( status == ClipboardLocked ); out[*len] = 0; *len = strlen(out); } // End if there's no current selection return True;} // End SendSelection/*---------------------------------------------------------------------- * Method to build a string from the current selection */voidMimeRichTextP::GetSelectionData(StringC& outbuf, TextTypeT type){ if ( !selectBegPos.textLine || !selectEndPos.textLine || selectBegPos == selectEndPos ) return; TextPosC *begPos = &selectBegPos; TextPosC *endPos = &selectEndPos;//// Swap points if they are reversed// if ( *begPos > *endPos ) { begPos = &selectEndPos; endPos = &selectBegPos; } sendExcerpt = False; // We don't send this with selections//// Add commands to bring us up to the initial state// if ( type != TT_PLAIN ) { TextPosC prevPos; if ( FindPosPrevCmd(*begPos, &prevPos) ) { TextStateC *begState = prevPos.State(); TextStateC nullState; GetStateCommands(nullState, *begState, outbuf, type); } }//// Add command in the selected range// GetRangeData(begPos, endPos, outbuf, type);//// Add commands to reset the state// if ( type != TT_PLAIN ) { TextStateC *endState = endPos->State(); TextStateC nullState; GetStateCommands(*endState, nullState, outbuf, type); } sendExcerpt = True; if ( debuglev > 1 ) cout <<"Selection buffer is: [" <<outbuf <<"]" <<endl;} // End GetSelectionData/*---------------------------------------------------------------------- * Method to build a string from the given range */voidMimeRichTextP::GetRangeData(TextPosC *pos1, TextPosC *pos2, StringC& outbuf, TextTypeT type, Boolean closeState, int lineSize){ TextPosC *begPos = pos1; TextPosC *endPos = pos2;//// Swap points if they are reversed// if ( *begPos > *endPos ) { begPos = pos2; endPos = pos1; }//// See if there's just one line involved// if ( begPos->textLine == endPos->textLine ) { GetLineText(begPos, endPos, outbuf, type, lineSize); } else {//// Read to the end of the start line// GetLineText(begPos, NULL, outbuf, type, lineSize);//// Add a newline// if ( type == TT_ENRICHED ) outbuf += '\n'; else if ( type == TT_RICH ) outbuf += "<nl>"; outbuf += '\n';//// Read all lines in-between start and end line// TextLineC *begLine = begPos->textLine; TextLineC *endLine = endPos->textLine; TextLineC *tline = begLine->next; while ( tline && tline != endLine ) { int oldLen = outbuf.size(); GetLineText(tline, outbuf, type, lineSize); int added = outbuf.size() - oldLen;//// Add a newline// if ( type == TT_ENRICHED && added ) outbuf += '\n'; else if ( type == TT_RICH ) outbuf += "<nl>"; outbuf += '\n'; tline = tline->next; }//// Read from the beginning of the end line// GetLineText(NULL, endPos, outbuf, type, lineSize); } // End if more than one line selected//// Get closing commands// if ( closeState && type != TT_PLAIN ) { TextStateC nullState; GetStateCommands(*endPos->State(), nullState, outbuf, type); }} // End GetRangeData/*---------------------------------------------------------------------- * Method to append the first text to the second, doubling any '<'s in * the process if the type is enriched. */voidMimeRichTextP::CopyText(StringC& src, StringC& dst, TextTypeT type, TextStateC *state, int lineSize){//// lineSize of 0 means we're not wrapping// if ( lineSize == 0 ) {//// Once folded, plain cannot be restored.// Enriched can always be restored so we can use 72 regardless// if ( type == TT_PLAIN ) lineSize = MAXINT; else lineSize = 72; }//// See how much we're trying to add// int remaining = src.size();//// See how much room is left on the current line// int pos = dst.RevPosOf('\n'); int wrapLen = lineSize - (dst.size() - pos - 1);//// If this line is full, see if there's a space where a break can be inserted// if ( wrapLen <= 2 ) { pos = dst.RevPosOf(' '); wrapLen = lineSize - (dst.size() - pos - 1); if ( wrapLen <= 2 ) { // There is no space //dst += "\n"; wrapLen = lineSize; } else {//// Insert break// char *cs = dst; cs[pos] = '\n';//// Add excerpting to plain text// if ( type == TT_PLAIN ) { int i; pos++; if ( sendExcerpt ) { for (i=0; i<state->Excerpt(); i++) { dst(pos,0) = excerptStr; pos += excerptStr.size(); wrapLen -= excerptStr.size(); } } for (i=0; i<state->LIndent(); i++) { dst(pos,0) = " "; pos += 3; wrapLen -= 3; } } } } u_int sstart = 0; CharC line;//// Wrap lines at lineSize columns// while ( remaining > 0 ) { Boolean split = False; if ( remaining > wrapLen ) {//// Look backward from position lineSize and see if we can find a space// pos = sstart + wrapLen; while ( pos > sstart && !isspace(src[pos]) ) pos--;//// If we found a space, end the line before it.// if ( pos > sstart ) { line = src(sstart, pos-sstart); sstart = pos + 1; remaining = src.size() - sstart; split = True; }//// If we didn't find a space to the left, look forward// else { pos = sstart + wrapLen + 1; while ( pos < src.size() && !isspace(src[pos]) ) pos++;//// If we found a space, insert a newline before the space// if ( pos < src.size() ) { line = src(sstart, pos-sstart); sstart = pos + 1; remaining = src.size() - sstart; split = True; } } } // End if there are more than lineSize characters remaining//// If we didn't or couldn't split, just use what's left// if ( !split ) { line = src(sstart, remaining); remaining = 0; }//// Look for "<" and replace with "<<"// u_int lstart = 0; if ( type == TT_ENRICHED ) { pos = line.PosOf('<'); while ( pos >= 0 ) {//// Copy from start pos to current pos and add two less-than's// dst += line(lstart, pos-lstart); dst += "<<"; lstart = pos + 1; pos = line.PosOf('<', lstart); } // End for each '<' } // End if enriched//// Copy to end.// int len = line.Length() - lstart; if ( len > 0 ) dst += line(lstart, len);//// Add newline if text remains// if ( remaining > 0 ) { dst += "\n"; wrapLen = lineSize; // Use this for all but the first line if ( type == TT_PLAIN ) { int i; if ( sendExcerpt ) { for (i=0; i<state->Excerpt(); i++) { dst += excerptStr; wrapLen -= excerptStr.size(); } } for (i=0; i<state->LIndent(); i++) { dst += " "; wrapLen -= 3; } } } // End more text to be added } // End while more source remains} // End CopyText/*---------------------------------------------------------------------- * Method to extract the text between the given positions. The positions * are assumed to be on the same line. If the start position is NULL, * the beginning of the line is used. If the end position is NULL, * the end of the line is used. The character at the end pos is not * returned. The type determines whether markup is included */voidMimeRichTextP::GetLineText(TextPosC *begPos, TextPosC *endPos, StringC& outbuf, TextTypeT type, int lineSize){ if ( !begPos && !endPos ) return; TextLineC *tl = begPos ? begPos->textLine : endPos->textLine; int begCmdPos = 0; int begStrPos = 0; if ( begPos ) { begCmdPos = begPos->cmdPos; begStrPos = begPos->strPos; } int endCmdPos; int endStrPos; if ( endPos ) { endCmdPos = endPos->cmdPos; endStrPos = endPos->strPos; } else { endCmdPos = tl->cmdList.size() - 1; endStrPos = tl->Cmd(endCmdPos)->LastPos(); } RichCmdC *cmd = tl->Cmd(begCmdPos); TextStateC *curState = &cmd->state; int i;//// Get opening commands// if ( type != TT_PLAIN ) { if ( begPos ) GetStateCommands(*begPos, outbuf, type); else { TextPosC pos(tl, begCmdPos, begStrPos); GetStateCommands(pos, outbuf, type); } } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -