File: | Text.c |
Location: | line 2005, column 10 |
Description: | Value stored to 'pos2' is never read |
1 | /*********************************************************** |
2 | |
3 | Copyright (c) 1987, 1988, 1994 X Consortium |
4 | |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy |
6 | of this software and associated documentation files (the "Software"), to deal |
7 | in the Software without restriction, including without limitation the rights |
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
9 | copies of the Software, and to permit persons to whom the Software is |
10 | furnished to do so, subject to the following conditions: |
11 | |
12 | The above copyright notice and this permission notice shall be included in |
13 | all copies or substantial portions of the Software. |
14 | |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
18 | X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
19 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
21 | |
22 | Except as contained in this notice, the name of the X Consortium shall not be |
23 | used in advertising or otherwise to promote the sale, use or other dealings |
24 | in this Software without prior written authorization from the X Consortium. |
25 | |
26 | |
27 | Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. |
28 | |
29 | All Rights Reserved |
30 | |
31 | Permission to use, copy, modify, and distribute this software and its |
32 | documentation for any purpose and without fee is hereby granted, |
33 | provided that the above copyright notice appear in all copies and that |
34 | both that copyright notice and this permission notice appear in |
35 | supporting documentation, and that the name of Digital not be |
36 | used in advertising or publicity pertaining to distribution of the |
37 | software without specific, written prior permission. |
38 | |
39 | DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING |
40 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL |
41 | DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR |
42 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
43 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, |
44 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS |
45 | SOFTWARE. |
46 | |
47 | ******************************************************************/ |
48 | |
49 | #ifdef HAVE_CONFIG_H1 |
50 | #include "config.h" |
51 | #endif |
52 | #include <X11/Xaw3d/Xaw3dP.h> |
53 | #include <X11/IntrinsicP.h> |
54 | #include <X11/StringDefs.h> |
55 | #include <X11/Shell.h> |
56 | #include <X11/Xatom.h> |
57 | #include <X11/Xutil.h> |
58 | #ifdef XAW_INTERNATIONALIZATION1 |
59 | #include "XawI18n.h" |
60 | #endif |
61 | #include <stdint.h> |
62 | #include <stdio.h> |
63 | #include <stdlib.h> |
64 | #include <X11/Xmu/Atoms.h> |
65 | #include <X11/Xmu/CharSet.h> |
66 | #include <X11/Xmu/Converters.h> |
67 | #include <X11/Xmu/StdSel.h> |
68 | #include <X11/Xmu/Misc.h> |
69 | #include <X11/Xaw3d/XawInit.h> |
70 | #include <X11/Xaw3d/Cardinals.h> |
71 | #include <X11/Xaw3d/Scrollbar.h> |
72 | #include <X11/Xaw3d/TextP.h> |
73 | #ifdef XAW_INTERNATIONALIZATION1 |
74 | #include <X11/Xaw3d/MultiSinkP.h> |
75 | #include <X11/Xaw3d/XawImP.h> |
76 | #endif |
77 | #include <X11/Xaw3d/ThreeDP.h> |
78 | #include <X11/Xfuncs.h> |
79 | #include <ctype.h> /* for isprint() */ |
80 | |
81 | #ifndef MAX_LEN_CT6 |
82 | #define MAX_LEN_CT6 6 /* for sequence: ESC $ ( A \xx \xx */ |
83 | #endif |
84 | |
85 | unsigned long FMT8BIT = 0L; |
86 | unsigned long XawFmt8Bit = 0L; |
87 | #ifdef XAW_INTERNATIONALIZATION1 |
88 | unsigned long XawFmtWide = 0L; |
89 | #endif |
90 | |
91 | #define SinkClearToBGXawTextSinkClearToBackground XawTextSinkClearToBackground |
92 | |
93 | #define SrcScanXawTextSourceScan XawTextSourceScan |
94 | #define SrcReadXawTextSourceRead XawTextSourceRead |
95 | #define SrcReplaceXawTextSourceReplace XawTextSourceReplace |
96 | #define SrcSearchXawTextSourceSearch XawTextSourceSearch |
97 | #define SrcCvtSelXawTextSourceConvertSelection XawTextSourceConvertSelection |
98 | #define SrcSetSelectionXawTextSourceSetSelection XawTextSourceSetSelection |
99 | |
100 | #define BIGNUM((Dimension)32023) ((Dimension)32023) |
101 | #define MULTI_CLICK_TIME500L 500L |
102 | |
103 | /* |
104 | * Compute a the maximum length of a cut buffer that we can pass at any |
105 | * time. The 64 allows for the overhead of the Change Property request. |
106 | */ |
107 | |
108 | #define MAX_CUT_LEN(dpy)(XMaxRequestSize(dpy) - 64) (XMaxRequestSize(dpy) - 64) |
109 | |
110 | #define IsValidLine(ctx, num)( ((num) == 0) || ((ctx)->text.lt.info[(num)].position != 0 ) ) ( ((num) == 0) || \ |
111 | ((ctx)->text.lt.info[(num)].position != 0) ) |
112 | |
113 | /* |
114 | * Defined in TextAction.c |
115 | */ |
116 | extern void _XawTextZapSelection(TextWidget, XEvent *, Boolean); |
117 | |
118 | |
119 | /* |
120 | * Defined in Text.c |
121 | */ |
122 | static void UnrealizeScrollbars(Widget, XtPointer, XtPointer); |
123 | static void VScroll(Widget, XtPointer, XtPointer); |
124 | static void VJump(Widget, XtPointer, XtPointer); |
125 | static void HScroll(Widget, XtPointer, XtPointer); |
126 | static void HJump(Widget, XtPointer, XtPointer); |
127 | static void ClearWindow(Widget); |
128 | static void DisplayTextWindow(Widget); |
129 | static void ModifySelection(TextWidget, XawTextPosition, XawTextPosition); |
130 | static void PushCopyQueue(TextWidget, int, int); |
131 | static void UpdateTextInLine(TextWidget, int, Position, Position); |
132 | static void UpdateTextInRectangle(TextWidget, XRectangle *); |
133 | static void PopCopyQueue(TextWidget); |
134 | static void FlushUpdate(TextWidget); |
135 | static Boolean LineAndXYForPosition(TextWidget, XawTextPosition, int *, |
136 | Position *, Position *); |
137 | static Boolean TranslateExposeRegion(TextWidget, XRectangle *); |
138 | static XawTextPosition FindGoodPosition(TextWidget, XawTextPosition); |
139 | static XawTextPosition _BuildLineTable(TextWidget, XawTextPosition, |
140 | XawTextPosition, int); |
141 | |
142 | void _XawTextAlterSelection(TextWidget, XawTextSelectionMode, |
143 | XawTextSelectionAction, String *, Cardinal *); |
144 | void _XawTextCheckResize(TextWidget); |
145 | void _XawTextClearAndCenterDisplay(TextWidget); |
146 | void _XawTextExecuteUpdate(TextWidget); |
147 | char *_XawTextGetText(TextWidget, XawTextPosition, XawTextPosition); |
148 | void _XawTextNeedsUpdating(TextWidget, XawTextPosition, XawTextPosition); |
149 | Atom * _XawTextSelectionList(TextWidget, String *, Cardinal); |
150 | void _XawTextSetScrollBars(TextWidget); |
151 | void _XawTextSetSelection(TextWidget, XawTextPosition, XawTextPosition, |
152 | String *, Cardinal); |
153 | void _XawTextShowPosition(TextWidget); |
154 | void _XawTextPrepareToUpdate(TextWidget); |
155 | int _XawTextReplace(TextWidget, XawTextPosition, XawTextPosition, XawTextBlock *); |
156 | void _XawTextVScroll(TextWidget, int); |
157 | |
158 | /**************************************************************** |
159 | * |
160 | * Full class record constant |
161 | * |
162 | ****************************************************************/ |
163 | |
164 | static XawTextSelectType defaultSelectTypes[] = { |
165 | XawselectPosition, XawselectWord, XawselectLine, XawselectParagraph, |
166 | XawselectAll, XawselectNull, |
167 | }; |
168 | |
169 | static XPointer defaultSelectTypesPtr = (XPointer)defaultSelectTypes; |
170 | extern char *_XawDefaultTextTranslations1, *_XawDefaultTextTranslations2, |
171 | *_XawDefaultTextTranslations3, *_XawDefaultTextTranslations4; |
172 | static Dimension defWidth = 100; |
173 | static Dimension defHeight = DEFAULT_TEXT_HEIGHT((Dimension)~0); |
174 | |
175 | #define offset(field) XtOffsetOf(TextRec, field)__builtin_offsetof(TextRec, field) |
176 | static XtResource resources[] = { |
177 | {XtNwidth((char*)&XtStrings[872]), XtCWidth((char*)&XtStrings[1510]), XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension), |
178 | offset(core.width), XtRDimension((char*)&XtStrings[1618]), (XtPointer)&defWidth}, |
179 | {XtNcursor"cursor", XtCCursor((char*)&XtStrings[976]), XtRCursor((char*)&XtStrings[1611]), sizeof(Cursor), |
180 | offset(simple.cursor), XtRString((char*)&XtStrings[1797]), "xterm"}, |
181 | {XtNheight((char*)&XtStrings[234]), XtCHeight((char*)&XtStrings[1051]), XtRDimension((char*)&XtStrings[1618]), sizeof(Dimension), |
182 | offset(core.height), XtRDimension((char*)&XtStrings[1618]), (XtPointer)&defHeight}, |
183 | {XtNdisplayPosition"displayPosition", XtCTextPosition((char*)&XtStrings[1435]), XtRInt((char*)&XtStrings[1718]), sizeof(XawTextPosition), |
184 | offset(text.lt.top), XtRImmediate((char*)&XtStrings[1695]), (XtPointer)0}, |
185 | {XtNinsertPosition((char*)&XtStrings[326]), XtCTextPosition((char*)&XtStrings[1435]), XtRInt((char*)&XtStrings[1718]), sizeof(XawTextPosition), |
186 | offset(text.insertPos), XtRImmediate((char*)&XtStrings[1695]),(XtPointer)0}, |
187 | {XtNleftMargin"leftMargin", XtCMargin((char*)&XtStrings[1182]), XtRPosition((char*)&XtStrings[1775]), sizeof (Position), |
188 | offset(text.r_margin.left), XtRImmediate((char*)&XtStrings[1695]), (XtPointer)2}, |
189 | {XtNrightMargin"rightMargin", XtCMargin((char*)&XtStrings[1182]), XtRPosition((char*)&XtStrings[1775]), sizeof (Position), |
190 | offset(text.r_margin.right), XtRImmediate((char*)&XtStrings[1695]), (XtPointer)4}, |
191 | {XtNtopMargin"topMargin", XtCMargin((char*)&XtStrings[1182]), XtRPosition((char*)&XtStrings[1775]), sizeof (Position), |
192 | offset(text.r_margin.top), XtRImmediate((char*)&XtStrings[1695]), (XtPointer)2}, |
193 | {XtNbottomMargin"bottomMargin", XtCMargin((char*)&XtStrings[1182]), XtRPosition((char*)&XtStrings[1775]), sizeof (Position), |
194 | offset(text.r_margin.bottom), XtRImmediate((char*)&XtStrings[1695]), (XtPointer)2}, |
195 | {XtNselectTypes"selectTypes", XtCSelectTypes"SelectTypes", XtRPointer((char*)&XtStrings[1767]), |
196 | sizeof(XawTextSelectType*), offset(text.sarray), |
197 | XtRPointer((char*)&XtStrings[1767]), (XtPointer)&defaultSelectTypesPtr}, |
198 | {XtNtextSource((char*)&XtStrings[761]), XtCTextSource((char*)&XtStrings[1457]), XtRWidget((char*)&XtStrings[1865]), sizeof (Widget), |
199 | offset(text.source), XtRImmediate((char*)&XtStrings[1695]), NULL((void*)0)}, |
200 | {XtNtextSink((char*)&XtStrings[752]), XtCTextSink((char*)&XtStrings[1448]), XtRWidget((char*)&XtStrings[1865]), sizeof (Widget), |
201 | offset(text.sink), XtRImmediate((char*)&XtStrings[1695]), NULL((void*)0)}, |
202 | {XtNdisplayCaret"displayCaret", XtCOutput"Output", XtRBoolean((char*)&XtStrings[1561]), sizeof(Boolean), |
203 | offset(text.display_caret), XtRImmediate((char*)&XtStrings[1695]), (XtPointer)True1}, |
204 | {XtNscrollVertical"scrollVertical", XtCScroll"Scroll", XtRScrollMode"ScrollMode", sizeof(XawTextScrollMode), |
205 | offset(text.scroll_vert), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) XawtextScrollNever}, |
206 | {XtNscrollHorizontal"scrollHorizontal", XtCScroll"Scroll", XtRScrollMode"ScrollMode", sizeof(XawTextScrollMode), |
207 | offset(text.scroll_horiz), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) XawtextScrollNever}, |
208 | {XtNwrap"wrap", XtCWrap"Wrap", XtRWrapMode"WrapMode", sizeof(XawTextWrapMode), |
209 | offset(text.wrap), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) XawtextWrapNever}, |
210 | {XtNresize((char*)&XtStrings[564]), XtCResize((char*)&XtStrings[1253]), XtRResizeMode"ResizeMode", sizeof(XawTextResizeMode), |
211 | offset(text.resize), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) XawtextResizeNever}, |
212 | {XtNautoFill"autoFill", XtCAutoFill"AutoFill", XtRBoolean((char*)&XtStrings[1561]), sizeof(Boolean), |
213 | offset(text.auto_fill), XtRImmediate((char*)&XtStrings[1695]), (XtPointer) FALSE0}, |
214 | {XtNunrealizeCallback((char*)&XtStrings[815]), XtCCallback((char*)&XtStrings[952]), XtRCallback((char*)&XtStrings[1569]), sizeof(XtPointer), |
215 | offset(text.unrealize_callbacks), XtRCallback((char*)&XtStrings[1569]), (XtPointer) NULL((void*)0)} |
216 | }; |
217 | #undef offset |
218 | |
219 | /* ARGSUSED */ |
220 | static void |
221 | CvtStringToScrollMode(XrmValuePtr args, Cardinal *num_args, XrmValuePtr fromVal, |
222 | XrmValuePtr toVal) |
223 | { |
224 | static XawTextScrollMode scrollMode; |
225 | static XrmQuark QScrollNever, QScrollAlways, QScrollWhenNeeded; |
226 | XrmQuark q; |
227 | char lowerName[40]; |
228 | static Boolean inited = FALSE0; |
229 | |
230 | if ( !inited ) { |
231 | QScrollNever = XrmPermStringToQuark(XtEtextScrollNever"never"); |
232 | QScrollWhenNeeded = XrmPermStringToQuark(XtEtextScrollWhenNeeded"whenneeded"); |
233 | QScrollAlways = XrmPermStringToQuark(XtEtextScrollAlways"always"); |
234 | inited = TRUE1; |
235 | } |
236 | |
237 | if (strlen ((char*) fromVal->addr) < sizeof lowerName) { |
238 | XmuCopyISOLatin1Lowered (lowerName, (char *)fromVal->addr); |
239 | q = XrmStringToQuark(lowerName); |
240 | |
241 | if (q == QScrollNever) scrollMode = XawtextScrollNever; |
242 | else if (q == QScrollWhenNeeded) scrollMode = XawtextScrollWhenNeeded; |
243 | else if (q == QScrollAlways) scrollMode = XawtextScrollAlways; |
244 | else { |
245 | toVal->size = 0; |
246 | toVal->addr = NULL((void*)0); |
247 | return; |
248 | } |
249 | toVal->size = sizeof scrollMode; |
250 | toVal->addr = (XPointer) &scrollMode; |
251 | return; |
252 | } |
253 | toVal->size = 0; |
254 | toVal->addr = NULL((void*)0); |
255 | } |
256 | |
257 | /* ARGSUSED */ |
258 | static void |
259 | CvtStringToWrapMode(XrmValuePtr args, Cardinal *num_args, XrmValuePtr fromVal, |
260 | XrmValuePtr toVal) |
261 | { |
262 | static XawTextWrapMode wrapMode; |
263 | static XrmQuark QWrapNever, QWrapLine, QWrapWord; |
264 | XrmQuark q; |
265 | char lowerName[BUFSIZ1024]; |
266 | static Boolean inited = FALSE0; |
267 | |
268 | if ( !inited ) { |
269 | QWrapNever = XrmPermStringToQuark(XtEtextWrapNever"never"); |
270 | QWrapLine = XrmPermStringToQuark(XtEtextWrapLine"line"); |
271 | QWrapWord = XrmPermStringToQuark(XtEtextWrapWord"word"); |
272 | inited = TRUE1; |
273 | } |
274 | |
275 | if (strlen ((char*) fromVal->addr) < sizeof lowerName) { |
276 | XmuCopyISOLatin1Lowered (lowerName, (char *)fromVal->addr); |
277 | q = XrmStringToQuark(lowerName); |
278 | |
279 | if (q == QWrapNever) wrapMode = XawtextWrapNever; |
280 | else if (q == QWrapLine) wrapMode = XawtextWrapLine; |
281 | else if (q == QWrapWord) wrapMode = XawtextWrapWord; |
282 | else { |
283 | toVal->size = 0; |
284 | toVal->addr = NULL((void*)0); |
285 | return; |
286 | } |
287 | toVal->size = sizeof wrapMode; |
288 | toVal->addr = (XPointer) &wrapMode; |
289 | return; |
290 | } |
291 | toVal->size = 0; |
292 | toVal->addr = NULL((void*)0); |
293 | } |
294 | |
295 | /* ARGSUSED */ |
296 | static void |
297 | CvtStringToResizeMode(XrmValuePtr args, Cardinal *num_args, XrmValuePtr fromVal, |
298 | XrmValuePtr toVal) |
299 | { |
300 | static XawTextResizeMode resizeMode; |
301 | static XrmQuark QResizeNever, QResizeWidth, QResizeHeight, QResizeBoth; |
302 | XrmQuark q; |
303 | char lowerName[40]; |
304 | static Boolean inited = FALSE0; |
305 | |
306 | if ( !inited ) { |
307 | QResizeNever = XrmPermStringToQuark(XtEtextResizeNever"never"); |
308 | QResizeWidth = XrmPermStringToQuark(XtEtextResizeWidth"width"); |
309 | QResizeHeight = XrmPermStringToQuark(XtEtextResizeHeight"height"); |
310 | QResizeBoth = XrmPermStringToQuark(XtEtextResizeBoth"both"); |
311 | inited = TRUE1; |
312 | } |
313 | |
314 | if (strlen ((char*) fromVal->addr) < sizeof lowerName) { |
315 | XmuCopyISOLatin1Lowered (lowerName, (char *)fromVal->addr); |
316 | q = XrmStringToQuark(lowerName); |
317 | |
318 | if (q == QResizeNever) resizeMode = XawtextResizeNever; |
319 | else if (q == QResizeWidth) resizeMode = XawtextResizeWidth; |
320 | else if (q == QResizeHeight) resizeMode = XawtextResizeHeight; |
321 | else if (q == QResizeBoth) resizeMode = XawtextResizeBoth; |
322 | else { |
323 | toVal->size = 0; |
324 | toVal->addr = NULL((void*)0); |
325 | return; |
326 | } |
327 | toVal->size = sizeof resizeMode; |
328 | toVal->addr = (XPointer) &resizeMode; |
329 | return; |
330 | } |
331 | toVal->size = 0; |
332 | toVal->addr = NULL((void*)0); |
333 | } |
334 | |
335 | static void |
336 | ClassInitialize(void) |
337 | { |
338 | int len1 = strlen (_XawDefaultTextTranslations1); |
339 | int len2 = strlen (_XawDefaultTextTranslations2); |
340 | int len3 = strlen (_XawDefaultTextTranslations3); |
341 | int len4 = strlen (_XawDefaultTextTranslations4); |
342 | char *buf = XtMalloc ((unsigned)(len1 + len2 + len3 + len4 + 1)); |
343 | char *cp = buf; |
344 | |
345 | if (!XawFmt8Bit) |
346 | FMT8BIT = XawFmt8Bit = XrmPermStringToQuark("FMT8BIT"); |
347 | #ifdef XAW_INTERNATIONALIZATION1 |
348 | if (!XawFmtWide) |
349 | XawFmtWide = XrmPermStringToQuark("FMTWIDE"); |
350 | #endif |
351 | |
352 | XawInitializeWidgetSet(); |
353 | |
354 | /* |
355 | * Set the number of actions. |
356 | */ |
357 | |
358 | textClassRec.core_class.num_actions = _XawTextActionsTableCount; |
359 | |
360 | (void) strcpy( cp, _XawDefaultTextTranslations1)__builtin___strcpy_chk (cp, _XawDefaultTextTranslations1, __builtin_object_size (cp, 2 > 1 ? 1 : 0)); cp += len1; |
361 | (void) strcpy( cp, _XawDefaultTextTranslations2)__builtin___strcpy_chk (cp, _XawDefaultTextTranslations2, __builtin_object_size (cp, 2 > 1 ? 1 : 0)); cp += len2; |
362 | (void) strcpy( cp, _XawDefaultTextTranslations3)__builtin___strcpy_chk (cp, _XawDefaultTextTranslations3, __builtin_object_size (cp, 2 > 1 ? 1 : 0)); cp += len3; |
363 | (void) strcpy( cp, _XawDefaultTextTranslations4)__builtin___strcpy_chk (cp, _XawDefaultTextTranslations4, __builtin_object_size (cp, 2 > 1 ? 1 : 0)); |
364 | textWidgetClass->core_class.tm_table = buf; |
365 | |
366 | XtAddConverter(XtRString((char*)&XtStrings[1797]), XtRScrollMode"ScrollMode", CvtStringToScrollMode, |
367 | (XtConvertArgList)NULL((void*)0), (Cardinal)0 ); |
368 | XtAddConverter(XtRString((char*)&XtStrings[1797]), XtRWrapMode"WrapMode", CvtStringToWrapMode, |
369 | (XtConvertArgList)NULL((void*)0), (Cardinal)0 ); |
370 | XtAddConverter(XtRString((char*)&XtStrings[1797]), XtRResizeMode"ResizeMode", CvtStringToResizeMode, |
371 | (XtConvertArgList)NULL((void*)0), (Cardinal)0 ); |
372 | } |
373 | |
374 | /* Function Name: PositionHScrollBar. |
375 | * Description: Positions the Horizontal scrollbar. |
376 | * Arguments: ctx - the text widget. |
377 | * Returns: none |
378 | */ |
379 | |
380 | static void |
381 | PositionHScrollBar(TextWidget ctx) |
382 | { |
383 | Widget vbar = ctx->text.vbar, hbar = ctx->text.hbar; |
384 | Position top, left = 0; |
385 | int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; |
386 | |
387 | if (ctx->text.hbar == NULL((void*)0)) return; |
388 | |
389 | if (vbar != NULL((void*)0)) |
390 | left += (Position) (vbar->core.width + vbar->core.border_width); |
391 | |
392 | XtResizeWidget( hbar, ctx->core.width - left - s, hbar->core.height, |
393 | hbar->core.border_width ); |
394 | |
395 | left = s / 2 - (Position) hbar->core.border_width; |
396 | if (left < 0) left = 0; |
397 | if (vbar != NULL((void*)0)) |
398 | left += (Position) (vbar->core.width + vbar->core.border_width); |
399 | |
400 | top = ctx->core.height - (hbar->core.height + hbar->core.border_width + s / 2); |
401 | |
402 | XtMoveWidget( hbar, left, top); |
403 | } |
404 | |
405 | /* Function Name: PositionVScrollBar. |
406 | * Description: Positions the Vertical scrollbar. |
407 | * Arguments: ctx - the text widget. |
408 | * Returns: none. |
409 | */ |
410 | |
411 | static void |
412 | PositionVScrollBar(TextWidget ctx) |
413 | { |
414 | Widget vbar = ctx->text.vbar; |
415 | Position pos; |
416 | Dimension bw; |
417 | int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; |
418 | |
419 | if (vbar == NULL((void*)0)) return; |
420 | bw = vbar->core.border_width; |
421 | |
422 | XtResizeWidget( vbar, vbar->core.width, ctx->core.height - s, bw); |
423 | pos = s / 2 - (Position)bw; |
424 | if (pos < 0) pos = 0; |
425 | |
426 | XtMoveWidget( vbar, pos, pos); |
427 | } |
428 | |
429 | static void |
430 | CreateVScrollBar(TextWidget ctx) |
431 | { |
432 | Widget vbar; |
433 | |
434 | if (ctx->text.vbar != NULL((void*)0)) return; |
435 | |
436 | ctx->text.vbar = vbar = |
437 | XtCreateWidget("vScrollbar", scrollbarWidgetClass, (Widget)ctx, |
438 | (ArgList) NULL((void*)0), ZERO((Cardinal)0)); |
439 | XtAddCallback( vbar, XtNscrollProc((char*)&XtStrings[591]), VScroll, (XtPointer)ctx ); |
440 | XtAddCallback( vbar, XtNjumpProc((char*)&XtStrings[370]), VJump, (XtPointer)ctx ); |
441 | if (ctx->text.hbar == NULL((void*)0)) |
442 | XtAddCallback((Widget) ctx, XtNunrealizeCallback((char*)&XtStrings[815]), UnrealizeScrollbars, |
443 | (XtPointer) NULL((void*)0)); |
444 | |
445 | ctx->text.r_margin.left += vbar->core.width + vbar->core.border_width; |
446 | ctx->text.margin.left = ctx->text.r_margin.left; |
447 | |
448 | PositionVScrollBar(ctx); |
449 | PositionHScrollBar(ctx); /* May modify location of Horiz. Bar. */ |
450 | |
451 | if (XtIsRealized((Widget)ctx)(XtWindowOfObject((Widget)ctx) != 0L)) { |
452 | XtRealizeWidget(vbar); |
453 | XtMapWidget(vbar)XMapWindow((((vbar)->core.screen)->display), ((vbar)-> core.window)); |
454 | } |
455 | } |
456 | |
457 | /* Function Name: DestroyVScrollBar |
458 | * Description: Removes a vertical ScrollBar. |
459 | * Arguments: ctx - the parent text widget. |
460 | * Returns: none. |
461 | */ |
462 | |
463 | static void |
464 | DestroyVScrollBar(TextWidget ctx) |
465 | { |
466 | Widget vbar = ctx->text.vbar; |
467 | |
468 | if (vbar == NULL((void*)0)) return; |
469 | |
470 | ctx->text.r_margin.left -= vbar->core.width + vbar->core.border_width; |
471 | ctx->text.margin.left = ctx->text.r_margin.left; |
472 | if (ctx->text.hbar == NULL((void*)0)) |
473 | XtRemoveCallback((Widget) ctx, XtNunrealizeCallback((char*)&XtStrings[815]), UnrealizeScrollbars, |
474 | (XtPointer) NULL((void*)0)); |
475 | XtDestroyWidget(vbar); |
476 | ctx->text.vbar = NULL((void*)0); |
477 | PositionHScrollBar(ctx); |
478 | } |
479 | |
480 | static void |
481 | CreateHScrollBar(TextWidget ctx) |
482 | { |
483 | Arg args[1]; |
484 | Widget hbar; |
485 | |
486 | if (ctx->text.hbar != NULL((void*)0)) return; |
487 | |
488 | XtSetArg(args[0], XtNorientation, XtorientHorizontal)((void)( (args[0]).name = (((char*)&XtStrings[505])), (args [0]).value = (XtArgVal)(XtorientHorizontal) )); |
489 | ctx->text.hbar = hbar = |
490 | XtCreateWidget("hScrollbar", scrollbarWidgetClass, (Widget)ctx, args, ONE((Cardinal)1)); |
491 | XtAddCallback( hbar, XtNscrollProc((char*)&XtStrings[591]), HScroll, (XtPointer)ctx ); |
492 | XtAddCallback( hbar, XtNjumpProc((char*)&XtStrings[370]), HJump, (XtPointer)ctx ); |
493 | if (ctx->text.vbar == NULL((void*)0)) |
494 | XtAddCallback((Widget) ctx, XtNunrealizeCallback((char*)&XtStrings[815]), UnrealizeScrollbars, |
495 | (XtPointer) NULL((void*)0)); |
496 | |
497 | /**/ |
498 | ctx->text.r_margin.bottom += hbar->core.height + hbar->core.border_width; |
499 | ctx->text.margin.bottom = ctx->text.r_margin.bottom; |
500 | /**/ |
501 | PositionHScrollBar(ctx); |
502 | if (XtIsRealized((Widget)ctx)(XtWindowOfObject((Widget)ctx) != 0L)) { |
503 | XtRealizeWidget(hbar); |
504 | XtMapWidget(hbar)XMapWindow((((hbar)->core.screen)->display), ((hbar)-> core.window)); |
505 | } |
506 | } |
507 | |
508 | /* Function Name: DestroyHScrollBar |
509 | * Description: Removes a horizontal ScrollBar. |
510 | * Arguments: ctx - the parent text widget. |
511 | * Returns: none. |
512 | */ |
513 | |
514 | static void |
515 | DestroyHScrollBar(TextWidget ctx) |
516 | { |
517 | Widget hbar = ctx->text.hbar; |
518 | |
519 | if (hbar == NULL((void*)0)) return; |
520 | |
521 | /**/ |
522 | ctx->text.r_margin.bottom -= hbar->core.height + hbar->core.border_width; |
523 | ctx->text.margin.bottom = ctx->text.r_margin.bottom; |
524 | /**/ |
525 | if (ctx->text.vbar == NULL((void*)0)) |
526 | XtRemoveCallback((Widget) ctx, XtNunrealizeCallback((char*)&XtStrings[815]), UnrealizeScrollbars, |
527 | (XtPointer) NULL((void*)0)); |
528 | XtDestroyWidget(hbar); |
529 | ctx->text.hbar = NULL((void*)0); |
530 | } |
531 | |
532 | /* ARGSUSED */ |
533 | static void |
534 | Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args) |
535 | { |
536 | TextWidget ctx = (TextWidget) new; |
537 | char error_buf[BUFSIZ1024]; |
538 | int s; |
539 | |
540 | ctx->text.threeD = XtVaCreateWidget("threeD", threeDWidgetClass, new, |
541 | XtNx((char*)&XtStrings[885]), 0, XtNy((char*)&XtStrings[887]), 0, |
542 | XtNwidth((char*)&XtStrings[872]), 10, XtNheight((char*)&XtStrings[234]), 10, /* dummy */ |
543 | NULL((void*)0)); |
544 | |
545 | s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; |
546 | |
547 | ctx->text.r_margin.left += s; |
548 | ctx->text.r_margin.right += s; |
549 | ctx->text.r_margin.top += s; |
550 | ctx->text.r_margin.bottom += s - 1; |
551 | |
552 | ctx->text.lt.lines = 0; |
553 | ctx->text.lt.info = NULL((void*)0); |
554 | memset(&(ctx->text.origSel), 0, sizeof(XawTextSelection))__builtin___memset_chk (&(ctx->text.origSel), 0, sizeof (XawTextSelection), __builtin_object_size (&(ctx->text .origSel), 0)); |
555 | memset(&(ctx->text.s), 0, sizeof(XawTextSelection))__builtin___memset_chk (&(ctx->text.s), 0, sizeof(XawTextSelection ), __builtin_object_size (&(ctx->text.s), 0)); |
556 | ctx->text.s.type = XawselectPosition; |
557 | ctx->text.salt = NULL((void*)0); |
558 | ctx->text.hbar = ctx->text.vbar = (Widget) NULL((void*)0); |
559 | ctx->text.lasttime = 0; /* ||| correct? */ |
560 | ctx->text.time = 0; /* ||| correct? */ |
561 | ctx->text.showposition = TRUE1; |
562 | ctx->text.lastPos = (ctx->text.source != NULL((void*)0)) ? GETLASTPOSXawTextSourceScan(ctx->text.source, 0, XawstAll, XawsdRight , 1, 1) : 0; |
563 | ctx->text.file_insert = NULL((void*)0); |
564 | ctx->text.search = NULL((void*)0); |
565 | ctx->text.updateFrom = (XawTextPosition *) XtMalloc((unsigned) ONE((Cardinal)1)); |
566 | ctx->text.updateTo = (XawTextPosition *) XtMalloc((unsigned) ONE((Cardinal)1)); |
567 | ctx->text.numranges = ctx->text.maxranges = 0; |
568 | ctx->text.gc = DefaultGCOfScreen(XtScreen(ctx))((((ctx)->core.screen))->default_gc); |
569 | ctx->text.hasfocus = FALSE0; |
570 | ctx->text.margin = ctx->text.r_margin; /* Strucure copy. */ |
571 | ctx->text.update_disabled = FALSE0; |
572 | ctx->text.old_insert = -1; |
573 | ctx->text.mult = 1; |
574 | ctx->text.single_char = FALSE0; |
575 | ctx->text.copy_area_offsets = NULL((void*)0); |
576 | ctx->text.salt2 = NULL((void*)0); |
577 | |
578 | if (ctx->core.height == DEFAULT_TEXT_HEIGHT((Dimension)~0)) { |
579 | ctx->core.height = VMargins(ctx)( (ctx)->text.margin.top + (ctx)->text.margin.bottom ); |
580 | if (ctx->text.sink != NULL((void*)0)) |
581 | ctx->core.height += XawTextSinkMaxHeight(ctx->text.sink, 1); |
582 | } |
583 | |
584 | if (ctx->text.scroll_vert != XawtextScrollNever) { |
585 | if ( (ctx->text.resize == XawtextResizeHeight) || |
586 | (ctx->text.resize == XawtextResizeBoth) ) { |
587 | (void) sprintf(error_buf, "Xaw Text Widget %s:\n %s %s.", ctx->core.name,__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Text Widget %s:\n %s %s.", ctx->core.name, "Vertical scrolling not allowed with height resize.\n" , "Vertical scrolling has been DEACTIVATED.") |
588 | "Vertical scrolling not allowed with height resize.\n",__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Text Widget %s:\n %s %s.", ctx->core.name, "Vertical scrolling not allowed with height resize.\n" , "Vertical scrolling has been DEACTIVATED.") |
589 | "Vertical scrolling has been DEACTIVATED.")__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Text Widget %s:\n %s %s.", ctx->core.name, "Vertical scrolling not allowed with height resize.\n" , "Vertical scrolling has been DEACTIVATED."); |
590 | XtAppWarning(XtWidgetToApplicationContext(new), error_buf); |
591 | ctx->text.scroll_vert = XawtextScrollNever; |
592 | } |
593 | else if (ctx->text.scroll_vert == XawtextScrollAlways) |
594 | CreateVScrollBar(ctx); |
595 | } |
596 | |
597 | if (ctx->text.scroll_horiz != XawtextScrollNever) { |
598 | if (ctx->text.wrap != XawtextWrapNever) { |
599 | (void) sprintf(error_buf, "Xaw Text Widget %s:\n %s %s.", ctx->core.name,__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Text Widget %s:\n %s %s.", ctx->core.name, "Horizontal scrolling not allowed with wrapping active.\n" , "Horizontal scrolling has been DEACTIVATED.") |
600 | "Horizontal scrolling not allowed with wrapping active.\n",__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Text Widget %s:\n %s %s.", ctx->core.name, "Horizontal scrolling not allowed with wrapping active.\n" , "Horizontal scrolling has been DEACTIVATED.") |
601 | "Horizontal scrolling has been DEACTIVATED.")__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Text Widget %s:\n %s %s.", ctx->core.name, "Horizontal scrolling not allowed with wrapping active.\n" , "Horizontal scrolling has been DEACTIVATED."); |
602 | XtAppWarning(XtWidgetToApplicationContext(new), error_buf); |
603 | ctx->text.scroll_horiz = XawtextScrollNever; |
604 | } |
605 | else if ( (ctx->text.resize == XawtextResizeWidth) || |
606 | (ctx->text.resize == XawtextResizeBoth) ) { |
607 | (void) sprintf(error_buf, "Xaw Text Widget %s:\n %s %s.", ctx->core.name,__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Text Widget %s:\n %s %s.", ctx->core.name, "Horizontal scrolling not allowed with width resize.\n" , "Horizontal scrolling has been DEACTIVATED.") |
608 | "Horizontal scrolling not allowed with width resize.\n",__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Text Widget %s:\n %s %s.", ctx->core.name, "Horizontal scrolling not allowed with width resize.\n" , "Horizontal scrolling has been DEACTIVATED.") |
609 | "Horizontal scrolling has been DEACTIVATED.")__builtin___sprintf_chk (error_buf, 0, __builtin_object_size ( error_buf, 2 > 1 ? 1 : 0), "Xaw Text Widget %s:\n %s %s.", ctx->core.name, "Horizontal scrolling not allowed with width resize.\n" , "Horizontal scrolling has been DEACTIVATED."); |
610 | XtAppWarning(XtWidgetToApplicationContext(new), error_buf); |
611 | ctx->text.scroll_horiz = XawtextScrollNever; |
612 | } |
613 | else if (ctx->text.scroll_horiz == XawtextScrollAlways) |
614 | CreateHScrollBar(ctx); |
615 | } |
616 | } |
617 | |
618 | static void |
619 | Realize(Widget w, Mask *valueMask, XSetWindowAttributes *attributes) |
620 | { |
621 | TextWidget ctx = (TextWidget)w; |
622 | |
623 | (*textClassRec.core_class.superclass->core_class.realize) |
624 | (w, valueMask, attributes); |
625 | |
626 | if (ctx->text.hbar != NULL((void*)0)) { /* Put up Hbar -- Must be first. */ |
627 | XtRealizeWidget(ctx->text.hbar); |
628 | XtMapWidget(ctx->text.hbar)XMapWindow((((ctx->text.hbar)->core.screen)->display ), ((ctx->text.hbar)->core.window)); |
629 | } |
630 | |
631 | if (ctx->text.vbar != NULL((void*)0)) { /* Put up Vbar. */ |
632 | XtRealizeWidget(ctx->text.vbar); |
633 | XtMapWidget(ctx->text.vbar)XMapWindow((((ctx->text.vbar)->core.screen)->display ), ((ctx->text.vbar)->core.window)); |
634 | } |
635 | |
636 | _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE1); |
637 | _XawTextSetScrollBars(ctx); |
638 | _XawTextCheckResize(ctx); |
639 | } |
640 | |
641 | /*ARGSUSED*/ |
642 | static void |
643 | UnrealizeScrollbars(Widget widget, XtPointer client, XtPointer call) |
644 | { |
645 | TextWidget ctx = (TextWidget) widget; |
646 | |
647 | if (ctx->text.hbar) |
648 | XtUnrealizeWidget(ctx->text.hbar); |
649 | if (ctx->text.vbar) |
650 | XtUnrealizeWidget(ctx->text.vbar); |
651 | } |
652 | |
653 | /* Utility routines for support of Text */ |
654 | |
655 | static void |
656 | _CreateCutBuffers(Display *d) |
657 | { |
658 | static struct _DisplayRec { |
659 | struct _DisplayRec *next; |
660 | Display *dpy; |
661 | } *dpy_list = NULL((void*)0); |
662 | struct _DisplayRec *dpy_ptr; |
663 | |
664 | for (dpy_ptr = dpy_list; dpy_ptr != NULL((void*)0); dpy_ptr = dpy_ptr->next) |
665 | if (dpy_ptr->dpy == d) return; |
666 | |
667 | dpy_ptr = XtNew(struct _DisplayRec)((struct _DisplayRec *) XtMalloc((unsigned) sizeof(struct _DisplayRec ))); |
668 | dpy_ptr->next = dpy_list; |
669 | dpy_ptr->dpy = d; |
670 | dpy_list = dpy_ptr; |
671 | |
672 | #define Create(buffer) \ |
673 | XChangeProperty(d, RootWindow(d, 0)((&((_XPrivDisplay)(d))->screens[0])->root), buffer, XA_STRING((Atom) 31), 8, \ |
674 | PropModeAppend2, NULL((void*)0), 0 ); |
675 | |
676 | Create( XA_CUT_BUFFER0((Atom) 9) ); |
677 | Create( XA_CUT_BUFFER1((Atom) 10) ); |
678 | Create( XA_CUT_BUFFER2((Atom) 11) ); |
679 | Create( XA_CUT_BUFFER3((Atom) 12) ); |
680 | Create( XA_CUT_BUFFER4((Atom) 13) ); |
681 | Create( XA_CUT_BUFFER5((Atom) 14) ); |
682 | Create( XA_CUT_BUFFER6((Atom) 15) ); |
683 | Create( XA_CUT_BUFFER7((Atom) 16) ); |
684 | |
685 | #undef Create |
686 | } |
687 | |
688 | /* |
689 | * Procedure to manage insert cursor visibility for editable text. It uses |
690 | * the value of ctx->insertPos and an implicit argument. In the event that |
691 | * position is immediately preceded by an eol graphic, then the insert cursor |
692 | * is displayed at the beginning of the next line. |
693 | */ |
694 | static void |
695 | InsertCursor (Widget w, XawTextInsertState state) |
696 | { |
697 | TextWidget ctx = (TextWidget)w; |
698 | Position x, y; |
699 | int line; |
700 | |
701 | if (ctx->text.lt.lines < 1) return; |
702 | |
703 | if ( LineAndXYForPosition(ctx, ctx->text.insertPos, &line, &x, &y) ) { |
704 | if (line < ctx->text.lt.lines) |
705 | y += (ctx->text.lt.info[line + 1].y - ctx->text.lt.info[line].y) + 1; |
706 | else |
707 | y += (ctx->text.lt.info[line].y - ctx->text.lt.info[line - 1].y) + 1; |
708 | |
709 | if (ctx->text.display_caret) |
710 | XawTextSinkInsertCursor(ctx->text.sink, x, y, state); |
711 | } |
712 | ctx->text.ev_x = x; |
713 | ctx->text.ev_y = y; |
714 | |
715 | /* Keep Input Method up to speed */ |
716 | |
717 | #ifdef XAW_INTERNATIONALIZATION1 |
718 | if ( ctx->simple.international ) { |
719 | Arg list[1]; |
720 | |
721 | XtSetArg (list[0], XtNinsertPosition, ctx->text.insertPos)((void)( (list[0]).name = (((char*)&XtStrings[326])), (list [0]).value = (XtArgVal)(ctx->text.insertPos) )); |
722 | _XawImSetValues (w, list, 1); |
723 | } |
724 | #endif |
725 | } |
726 | |
727 | /* |
728 | * Procedure to register a span of text that is no longer valid on the display |
729 | * It is used to avoid a number of small, and potentially overlapping, screen |
730 | * updates. |
731 | */ |
732 | |
733 | void |
734 | _XawTextNeedsUpdating(TextWidget ctx, XawTextPosition left, XawTextPosition right) |
735 | { |
736 | int i; |
737 | if (left < right) { |
738 | for (i = 0; i < ctx->text.numranges; i++) { |
739 | if (left <= ctx->text.updateTo[i] && right >= ctx->text.updateFrom[i]) { |
740 | ctx->text.updateFrom[i] = Min(left, ctx->text.updateFrom[i])(((left) < (ctx->text.updateFrom[i])) ? (left) : (ctx-> text.updateFrom[i])); |
741 | ctx->text.updateTo[i] = Max(right, ctx->text.updateTo[i])(((right) > (ctx->text.updateTo[i])) ? (right) : (ctx-> text.updateTo[i])); |
742 | return; |
743 | } |
744 | } |
745 | ctx->text.numranges++; |
746 | if (ctx->text.numranges > ctx->text.maxranges) { |
747 | ctx->text.maxranges = ctx->text.numranges; |
748 | i = ctx->text.maxranges * sizeof(XawTextPosition); |
749 | ctx->text.updateFrom = (XawTextPosition *) |
750 | XtRealloc((char *)ctx->text.updateFrom, (unsigned) i); |
751 | ctx->text.updateTo = (XawTextPosition *) |
752 | XtRealloc((char *)ctx->text.updateTo, (unsigned) i); |
753 | } |
754 | ctx->text.updateFrom[ctx->text.numranges - 1] = left; |
755 | ctx->text.updateTo[ctx->text.numranges - 1] = right; |
756 | } |
757 | } |
758 | |
759 | /* |
760 | * Procedure to read a span of text in Ascii form. This is purely a hack and |
761 | * we probably need to add a function to sources to provide this functionality. |
762 | * [note: this is really a private procedure but is used in multiple modules]. |
763 | */ |
764 | |
765 | char * |
766 | _XawTextGetText(TextWidget ctx, XawTextPosition left, XawTextPosition right) |
767 | { |
768 | char *result, *tempResult; |
769 | XawTextBlock text; |
770 | int bytes; |
771 | |
772 | if (_XawTextFormat(ctx) == XawFmt8Bit) |
773 | bytes = sizeof(unsigned char); |
774 | #ifdef XAW_INTERNATIONALIZATION1 |
775 | else if (_XawTextFormat(ctx) == XawFmtWide) |
776 | bytes = sizeof(wchar_t); |
777 | #endif |
778 | else /* if there is another fomat, add here */ |
779 | bytes = 1; |
780 | |
781 | /* leave space for ZERO */ |
782 | tempResult=result=XtMalloc( (unsigned)(((Cardinal)(right-left))+ONE((Cardinal)1) )* bytes); |
783 | while (left < right) { |
784 | left = SrcReadXawTextSourceRead(ctx->text.source, left, &text, (int)(right - left)); |
785 | if (!text.length) |
786 | break; |
787 | memmove(tempResult, text.ptr, text.length * bytes)__builtin___memmove_chk (tempResult, text.ptr, text.length * bytes , __builtin_object_size (tempResult, 0)); |
788 | tempResult += text.length * bytes; |
789 | } |
790 | |
791 | if (bytes == sizeof(wchar_t)) |
792 | *((wchar_t*)tempResult) = (wchar_t)0; |
793 | else |
794 | *tempResult = '\0'; |
795 | return(result); |
796 | } |
797 | |
798 | /* Like _XawTextGetText, but enforces ICCCM STRING type encoding. This |
799 | routine is currently used to put just the ASCII chars in the selection into a |
800 | cut buffer. */ |
801 | |
802 | char * |
803 | _XawTextGetSTRING(TextWidget ctx, XawTextPosition left, XawTextPosition right) |
804 | { |
805 | unsigned char *s; |
806 | unsigned char c; |
807 | long i, j, n; |
808 | |
809 | /* allow ESC in accordance with ICCCM */ |
810 | #ifdef XAW_INTERNATIONALIZATION1 |
811 | if (_XawTextFormat(ctx) == XawFmtWide) { |
812 | MultiSinkObject sink = (MultiSinkObject) ctx->text.sink; |
813 | wchar_t *ws, wc; |
814 | ws = (wchar_t *)_XawTextGetText(ctx, left, right); |
815 | n = wcslen(ws); |
816 | for (j = 0, i = 0; j < n; j++) { |
817 | wc = ws[j]; |
818 | if (XwcTextEscapement (sink->multi_sink.fontset, &wc, 1) || |
819 | (wc == _Xaw_atowc(XawTAB0x09)) || (wc == _Xaw_atowc(XawLF0x0a)) || (wc == _Xaw_atowc(XawESC0x1b))) |
820 | ws[i++] = wc; |
821 | } |
822 | ws[i] = (wchar_t)0; |
823 | return (char *)ws; |
824 | } else |
825 | #endif |
826 | { |
827 | s = (unsigned char *)_XawTextGetText(ctx, left, right); |
828 | /* only HT and NL control chars are allowed, strip out others */ |
829 | n = strlen((char *)s); |
830 | i = 0; |
831 | for (j = 0; j < n; j++) { |
832 | c = s[j]; |
833 | if (((c >= 0x20) && c <= 0x7f) || |
834 | (c >= 0xa0) || (c == XawTAB0x09) || (c == XawLF0x0a) || (c == XawESC0x1b)) { |
835 | s[i] = c; |
836 | i++; |
837 | } |
838 | } |
839 | s[i] = 0; |
840 | return (char *)s; |
841 | } |
842 | #undef ESC |
843 | |
844 | } |
845 | |
846 | /* |
847 | * This routine maps an x and y position in a window that is displaying text |
848 | * into the corresponding position in the source. |
849 | * |
850 | * NOTE: it is illegal to call this routine unless there is a valid line table! |
851 | */ |
852 | |
853 | /*** figure out what line it is on ***/ |
854 | |
855 | static XawTextPosition |
856 | PositionForXY (TextWidget ctx, Position x, Position y) |
857 | { |
858 | int fromx, line, width, height; |
859 | XawTextPosition position; |
860 | |
861 | if (ctx->text.lt.lines == 0) return 0; |
862 | |
863 | for (line = 0; line < ctx->text.lt.lines - 1; line++) { |
864 | if (y <= ctx->text.lt.info[line + 1].y) |
865 | break; |
866 | } |
867 | position = ctx->text.lt.info[line].position; |
868 | if (position >= ctx->text.lastPos) |
869 | return(ctx->text.lastPos); |
870 | fromx = (int) ctx->text.margin.left; |
871 | XawTextSinkFindPosition( ctx->text.sink, position, fromx, x - fromx, |
872 | FALSE0, &position, &width, &height); |
873 | if (position > ctx->text.lastPos) return(ctx->text.lastPos); |
874 | if (position >= ctx->text.lt.info[line + 1].position) |
875 | position = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.lt.info[line + 1].position, |
876 | XawstPositions, XawsdLeft, 1, TRUE1); |
877 | return(position); |
878 | } |
879 | |
880 | /* |
881 | * This routine maps a source position in to the corresponding line number |
882 | * of the text that is displayed in the window. |
883 | * |
884 | * NOTE: It is illegal to call this routine unless there is a valid line table! |
885 | */ |
886 | |
887 | static int |
888 | LineForPosition (TextWidget ctx, XawTextPosition position) |
889 | { |
890 | int line; |
891 | |
892 | for (line = 0; line < ctx->text.lt.lines; line++) |
893 | if (position < ctx->text.lt.info[line + 1].position) |
894 | break; |
895 | return(line); |
896 | } |
897 | |
898 | /* |
899 | * This routine maps a source position into the corresponding line number |
900 | * and the x, y coordinates of the text that is displayed in the window. |
901 | * |
902 | * NOTE: It is illegal to call this routine unless there is a valid line table! |
903 | */ |
904 | |
905 | static Boolean |
906 | LineAndXYForPosition(TextWidget ctx, XawTextPosition pos, int *line, |
907 | Position *x, Position *y) |
908 | { |
909 | XawTextPosition linePos, endPos; |
910 | Boolean visible; |
911 | int realW, realH; |
912 | |
913 | *line = 0; |
914 | *x = ctx->text.margin.left; |
915 | *y = ctx->text.margin.top; |
916 | if ((visible = IsPositionVisible(ctx, pos)(pos >= ctx->text.lt.info[0].position && pos < ctx->text.lt.info[ctx->text.lt.lines].position))) { |
917 | *line = LineForPosition(ctx, pos); |
918 | *y = ctx->text.lt.info[*line].y; |
919 | *x = ctx->text.margin.left; |
920 | linePos = ctx->text.lt.info[*line].position; |
921 | XawTextSinkFindDistance( ctx->text.sink, linePos, |
922 | *x, pos, &realW, &endPos, &realH); |
923 | *x += realW; |
924 | } |
925 | return(visible); |
926 | } |
927 | |
928 | /* |
929 | * This routine builds a line table. It does this by starting at the |
930 | * specified position and measuring text to determine the staring position |
931 | * of each line to be displayed. It also determines and saves in the |
932 | * linetable all the required metrics for displaying a given line (e.g. |
933 | * x offset, y offset, line length, etc.). |
934 | */ |
935 | |
936 | void |
937 | _XawTextBuildLineTable ( |
938 | TextWidget ctx, |
939 | XawTextPosition position, |
940 | _XtBooleanint force_rebuild) |
941 | { |
942 | Dimension height = 0; |
943 | int lines = 0; |
944 | Cardinal size; |
945 | |
946 | if ((int)ctx->core.height > VMargins(ctx)( (ctx)->text.margin.top + (ctx)->text.margin.bottom )) { |
947 | height = ctx->core.height - VMargins(ctx)( (ctx)->text.margin.top + (ctx)->text.margin.bottom ); |
948 | lines = XawTextSinkMaxLines(ctx->text.sink, height); |
949 | } |
950 | size = sizeof(XawTextLineTableEntry) * (lines + 1); |
951 | |
952 | if ( (lines != ctx->text.lt.lines) || (ctx->text.lt.info == NULL((void*)0)) ) { |
953 | ctx->text.lt.info = (XawTextLineTableEntry *) XtRealloc((char *) ctx->text. |
954 | lt.info, size); |
955 | ctx->text.lt.lines = lines; |
956 | force_rebuild = TRUE1; |
957 | } |
958 | |
959 | if ( force_rebuild || (position != ctx->text.lt.top) ) { |
960 | memset(ctx->text.lt.info, 0, size)__builtin___memset_chk (ctx->text.lt.info, 0, size, __builtin_object_size (ctx->text.lt.info, 0)); |
961 | (void) _BuildLineTable(ctx, ctx->text.lt.top = position, zeroPosition((XawTextPosition) 0), 0); |
962 | } |
963 | } |
964 | |
965 | /* |
966 | * This assumes that the line table does not change size. |
967 | */ |
968 | |
969 | static XawTextPosition |
970 | _BuildLineTable(TextWidget ctx, XawTextPosition position, |
971 | XawTextPosition min_pos, int line) |
972 | { |
973 | XawTextLineTableEntry * lt = ctx->text.lt.info + line; |
974 | XawTextPosition endPos; |
975 | Position y; |
976 | int count, width, realW, realH; |
977 | Widget src = ctx->text.source; |
978 | |
979 | if ( ((ctx->text.resize == XawtextResizeWidth) || |
980 | (ctx->text.resize == XawtextResizeBoth) ) || |
981 | (ctx->text.wrap == XawtextWrapNever) ) |
982 | width = BIGNUM((Dimension)32023); |
983 | else |
984 | width = Max(0, ((int)ctx->core.width - (int)HMargins(ctx)))(((0) > (((int)ctx->core.width - (int)( (ctx)->text. margin.left + (ctx)->text.margin.right )))) ? (0) : (((int )ctx->core.width - (int)( (ctx)->text.margin.left + (ctx )->text.margin.right )))); |
985 | |
986 | y = ( (line == 0) ? ctx->text.margin.top : lt->y ); |
987 | |
988 | /* CONSTCOND */ |
989 | while ( TRUE1 ) { |
990 | lt->y = y; |
991 | lt->position = position; |
992 | |
993 | XawTextSinkFindPosition( ctx->text.sink, position, ctx->text.margin.left, |
994 | width, ctx->text.wrap == XawtextWrapWord, |
995 | &endPos, &realW, &realH); |
996 | lt->textWidth = realW; |
997 | y += realH; |
998 | |
999 | if (ctx->text.wrap == XawtextWrapNever) |
1000 | endPos = SrcScanXawTextSourceScan(src, position, XawstEOL, XawsdRight, 1, TRUE1); |
1001 | |
1002 | if ( endPos == ctx->text.lastPos) { /* We have reached the end. */ |
1003 | if(SrcScanXawTextSourceScan(src, position, XawstEOL, XawsdRight, 1, FALSE0) == endPos) |
1004 | break; |
1005 | } |
1006 | |
1007 | ++lt; |
1008 | ++line; |
1009 | if ( (line > ctx->text.lt.lines) || |
1010 | ((lt->position == (position = endPos)) && (position > min_pos)) ) |
1011 | return(position); |
1012 | } |
1013 | |
1014 | /* |
1015 | * If we are at the end of the buffer put two special lines in the table. |
1016 | * |
1017 | * a) Both have position > text.lastPos and lt->textWidth = 0. |
1018 | * b) The first has a real height, and the second has a height that |
1019 | * is the rest of the screen. |
1020 | * |
1021 | * I could fill in the rest of the table with valid heights and a large |
1022 | * lastPos, but this method keeps the number of fill regions down to a |
1023 | * minimum. |
1024 | * |
1025 | * One valid entry is needed at the end of the table so that the cursor |
1026 | * does not jump off the bottom of the window. |
1027 | */ |
1028 | |
1029 | for ( count = 0; count < 2 ; count++) |
1030 | if (line++ < ctx->text.lt.lines) { /* make sure not to run of the end. */ |
1031 | (++lt)->y = (count == 0) ? y : ctx->core.height |
1032 | - 2 * ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; |
1033 | lt->textWidth = 0; |
1034 | lt->position = ctx->text.lastPos + 100; |
1035 | } |
1036 | |
1037 | if (line < ctx->text.lt.lines) /* Clear out rest of table. */ |
1038 | memset((lt + 1), 0,__builtin___memset_chk ((lt + 1), 0, (ctx->text.lt.lines - line) * sizeof(XawTextLineTableEntry), __builtin_object_size ((lt + 1), 0)) |
1039 | (ctx->text.lt.lines - line) * sizeof(XawTextLineTableEntry) )__builtin___memset_chk ((lt + 1), 0, (ctx->text.lt.lines - line) * sizeof(XawTextLineTableEntry), __builtin_object_size ((lt + 1), 0)); |
1040 | |
1041 | ctx->text.lt.info[ctx->text.lt.lines].position = lt->position; |
1042 | |
1043 | return(endPos); |
1044 | } |
1045 | |
1046 | /* Function Name: GetWidestLine |
1047 | * Description: Returns the width (in pixels) of the widest line that |
1048 | * is currently visable. |
1049 | * Arguments: ctx - the text widget. |
1050 | * Returns: the width of the widest line. |
1051 | * |
1052 | * NOTE: This function requires a valid line table. |
1053 | */ |
1054 | |
1055 | static Dimension |
1056 | GetWidestLine(TextWidget ctx) |
1057 | { |
1058 | int i; |
1059 | Dimension widest; |
1060 | XawTextLineTablePtr lt = &(ctx->text.lt); |
1061 | |
1062 | for (i = 0, widest = 1 ; i < lt->lines ; i++) |
1063 | if (widest < lt->info[i].textWidth) |
1064 | widest = lt->info[i].textWidth; |
1065 | |
1066 | return(widest); |
1067 | } |
1068 | |
1069 | static void |
1070 | CheckVBarScrolling(TextWidget ctx) |
1071 | { |
1072 | float first, last; |
1073 | Boolean temp = (ctx->text.vbar == NULL((void*)0)); |
1074 | |
1075 | if (ctx->text.scroll_vert == XawtextScrollNever) return; |
1076 | |
1077 | if ( (ctx->text.lastPos > 0) && (ctx->text.lt.lines > 0)) { |
1078 | first = ctx->text.lt.top; |
1079 | first /= (float) ctx->text.lastPos; |
1080 | last = ctx->text.lt.info[ctx->text.lt.lines].position; |
1081 | if ( ctx->text.lt.info[ctx->text.lt.lines].position < ctx->text.lastPos ) |
1082 | last /= (float) ctx->text.lastPos; |
1083 | else |
1084 | last = 1.0; |
1085 | |
1086 | if (ctx->text.scroll_vert == XawtextScrollWhenNeeded) { |
1087 | int line; |
1088 | XawTextPosition last_pos; |
1089 | Position y = ctx->core.height - ctx->text.margin.bottom; |
1090 | |
1091 | if (ctx->text.hbar != NULL((void*)0)) |
1092 | y -= (ctx->text.hbar->core.height + |
1093 | 2 * ctx->text.hbar->core.border_width); |
1094 | |
1095 | last_pos = PositionForXY(ctx, (Position) ctx->core.width, y); |
1096 | line = LineForPosition(ctx, last_pos); |
1097 | |
1098 | if ( (y < ctx->text.lt.info[line + 1].y) || ((last - first) < 1.0) ) |
1099 | CreateVScrollBar(ctx); |
1100 | else |
1101 | DestroyVScrollBar(ctx); |
1102 | } |
1103 | |
1104 | if (ctx->text.vbar != NULL((void*)0)) |
1105 | XawScrollbarSetThumb(ctx->text.vbar, first, last - first); |
1106 | |
1107 | if ( (ctx->text.vbar == NULL((void*)0)) != temp) { |
1108 | _XawTextNeedsUpdating(ctx, zeroPosition((XawTextPosition) 0), ctx->text.lastPos); |
1109 | if (ctx->text.vbar == NULL((void*)0)) |
1110 | _XawTextBuildLineTable (ctx, zeroPosition((XawTextPosition) 0), FALSE0); |
1111 | } |
1112 | } |
1113 | else if (ctx->text.vbar != NULL((void*)0)) { |
1114 | if (ctx->text.scroll_vert == XawtextScrollWhenNeeded) |
1115 | DestroyVScrollBar(ctx); |
1116 | else if (ctx->text.scroll_vert == XawtextScrollAlways) |
1117 | XawScrollbarSetThumb(ctx->text.vbar, 0.0, 1.0); |
1118 | } |
1119 | } |
1120 | |
1121 | /* |
1122 | * This routine is used by Text to notify an associated scrollbar of the |
1123 | * correct metrics (position and shown fraction) for the text being currently |
1124 | * displayed in the window. |
1125 | */ |
1126 | |
1127 | void |
1128 | _XawTextSetScrollBars(TextWidget ctx) |
1129 | { |
1130 | float first, last, widest; |
1131 | Boolean temp = (ctx->text.hbar == NULL((void*)0)); |
1132 | Boolean vtemp = (ctx->text.vbar == NULL((void*)0)); |
1133 | int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; |
1134 | |
1135 | CheckVBarScrolling(ctx); |
1136 | |
1137 | if (ctx->text.scroll_horiz == XawtextScrollNever) return; |
1138 | |
1139 | if (ctx->text.vbar != NULL((void*)0)) |
1140 | widest = (int)(ctx->core.width - ctx->text.vbar->core.width - |
1141 | 2 * s - ctx->text.vbar->core.border_width); |
1142 | else |
1143 | widest = ctx->core.width - 2 * s; |
1144 | widest /= (last = GetWidestLine(ctx)); |
1145 | if (ctx->text.scroll_horiz == XawtextScrollWhenNeeded) { |
1146 | if (widest < 1.0) |
1147 | CreateHScrollBar(ctx); |
1148 | else |
1149 | DestroyHScrollBar(ctx); |
1150 | } |
1151 | |
1152 | if ( (ctx->text.hbar == NULL((void*)0)) != temp ) { |
1153 | _XawTextBuildLineTable (ctx, ctx->text.lt.top, TRUE1); |
1154 | CheckVBarScrolling(ctx); /* Recheck need for vbar, now that we added |
1155 | or removed the hbar.*/ |
1156 | } |
1157 | |
1158 | if (ctx->text.hbar != NULL((void*)0)) { |
1159 | first = ctx->text.r_margin.left - ctx->text.margin.left; |
1160 | first /= last; |
1161 | XawScrollbarSetThumb(ctx->text.hbar, first, widest); |
1162 | } |
1163 | |
1164 | if (((ctx->text.hbar == NULL((void*)0)) && (ctx->text.margin.left != |
1165 | ctx->text.r_margin.left)) || |
1166 | (ctx->text.vbar == NULL((void*)0)) != vtemp) |
1167 | { |
1168 | ctx->text.margin.left = ctx->text.r_margin.left; |
1169 | _XawTextNeedsUpdating(ctx, zeroPosition((XawTextPosition) 0), ctx->text.lastPos); |
1170 | FlushUpdate(ctx); |
1171 | } |
1172 | } |
1173 | |
1174 | /* |
1175 | * The routine will scroll the displayed text by lines. If the arg is |
1176 | * positive, move up; otherwise, move down. [note: this is really a private |
1177 | * procedure but is used in multiple modules]. |
1178 | */ |
1179 | |
1180 | void |
1181 | _XawTextVScroll(TextWidget ctx, int n) |
1182 | { |
1183 | XawTextPosition top, target; |
1184 | int y; |
1185 | Arg list[1]; |
1186 | XawTextLineTable * lt = &(ctx->text.lt); |
1187 | int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; |
1188 | |
1189 | if (abs(n) > ctx->text.lt.lines) |
1190 | n = (n > 0) ? ctx->text.lt.lines : -ctx->text.lt.lines; |
1191 | |
1192 | if (n == 0) return; |
1193 | |
1194 | if (n > 0) { |
1195 | if ( IsValidLine(ctx, n)( ((n) == 0) || ((ctx)->text.lt.info[(n)].position != 0) ) ) |
1196 | top = Min(lt->info[n].position, ctx->text.lastPos)(((lt->info[n].position) < (ctx->text.lastPos)) ? (lt ->info[n].position) : (ctx->text.lastPos)); |
1197 | else |
1198 | top = ctx->text.lastPos; |
1199 | |
1200 | y = IsValidLine(ctx, n)( ((n) == 0) || ((ctx)->text.lt.info[(n)].position != 0) ) ? lt->info[n].y : ctx->core.height - 2 * s; |
1201 | _XawTextBuildLineTable(ctx, top, FALSE0); |
1202 | if (top >= ctx->text.lastPos) |
1203 | DisplayTextWindow( (Widget) ctx); |
1204 | else { |
1205 | XCopyArea(XtDisplay(ctx)(((ctx)->core.screen)->display), XtWindow(ctx)((ctx)->core.window), XtWindow(ctx)((ctx)->core.window), ctx->text.gc, |
1206 | s, y, (int)ctx->core.width - 2 * s, (int)ctx->core.height - y - s, |
1207 | s, ctx->text.margin.top); |
1208 | |
1209 | PushCopyQueue(ctx, 0, (int) -y); |
1210 | SinkClearToBGXawTextSinkClearToBackground(ctx->text.sink, |
1211 | (Position) s, |
1212 | (Position) (ctx->text.margin.top + ctx->core.height - y - s), |
1213 | (Dimension) ctx->core.width - 2 * s, |
1214 | (Dimension) ctx->core.height - 2 * s); |
1215 | |
1216 | if (n < lt->lines) n++; /* update descenders at bottom */ |
1217 | _XawTextNeedsUpdating(ctx, lt->info[lt->lines - n].position, |
1218 | ctx->text.lastPos); |
1219 | _XawTextSetScrollBars(ctx); |
1220 | } |
1221 | } |
1222 | else { |
1223 | XawTextPosition updateTo; |
1224 | unsigned int height, clear_height; |
1225 | |
1226 | n = -n; |
1227 | target = lt->top; |
1228 | top = SrcScanXawTextSourceScan(ctx->text.source, target, XawstEOL, |
1229 | XawsdLeft, n+1, FALSE0); |
1230 | |
1231 | _XawTextBuildLineTable(ctx, top, FALSE0); |
1232 | y = IsValidLine(ctx, n)( ((n) == 0) || ((ctx)->text.lt.info[(n)].position != 0) ) ? lt->info[n].y : ctx->core.height - 2 * s; |
1233 | updateTo = IsValidLine(ctx, n)( ((n) == 0) || ((ctx)->text.lt.info[(n)].position != 0) ) ? lt->info[n].position : ctx->text.lastPos; |
1234 | if (IsValidLine(ctx, lt->lines - n)( ((lt->lines - n) == 0) || ((ctx)->text.lt.info[(lt-> lines - n)].position != 0) )) |
1235 | height = lt->info[lt->lines-n].y - ctx->text.margin.top; |
1236 | else if (ctx->core.height - HMargins(ctx)( (ctx)->text.margin.left + (ctx)->text.margin.right )) |
1237 | height = ctx->core.height - HMargins(ctx)( (ctx)->text.margin.left + (ctx)->text.margin.right ); |
1238 | else |
1239 | height = 0; |
1240 | if (y > (int) ctx->text.margin.top) |
1241 | clear_height = y - ctx->text.margin.top; |
1242 | else |
1243 | clear_height = 0; |
1244 | |
1245 | if ( updateTo == target ) { |
1246 | XCopyArea(XtDisplay(ctx)(((ctx)->core.screen)->display), XtWindow(ctx)((ctx)->core.window), XtWindow(ctx)((ctx)->core.window), ctx->text.gc, |
1247 | s, ctx->text.margin.top, (int) ctx->core.width - 2 * s, |
1248 | height, s, y); |
1249 | PushCopyQueue(ctx, 0, (int) y); |
1250 | SinkClearToBGXawTextSinkClearToBackground(ctx->text.sink, (Position) s, ctx->text.margin.top, |
1251 | (Dimension) ctx->core.width - 2 * s, (Dimension) clear_height); |
1252 | |
1253 | _XawTextNeedsUpdating(ctx, lt->info[0].position, updateTo); |
1254 | _XawTextSetScrollBars(ctx); |
1255 | } |
1256 | else if (lt->top != target) |
1257 | DisplayTextWindow((Widget)ctx); |
1258 | } |
1259 | XtSetArg (list[0], XtNinsertPosition, ctx->text.lt.top+ctx->text.lt.lines)((void)( (list[0]).name = (((char*)&XtStrings[326])), (list [0]).value = (XtArgVal)(ctx->text.lt.top+ctx->text.lt.lines ) )); |
1260 | #ifdef XAW_INTERNATIONALIZATION1 |
1261 | _XawImSetValues ((Widget) ctx, list, 1); |
1262 | #endif |
1263 | |
1264 | _ShadowSurroundedBox((Widget)ctx, (ThreeDWidget)ctx->text.threeD, |
1265 | 0, 0, ctx->core.width, ctx->core.height, |
1266 | ((ThreeDWidget)ctx->text.threeD)->threeD.relief, False0); |
1267 | } |
1268 | |
1269 | /*ARGSUSED*/ |
1270 | static void |
1271 | HScroll(Widget w, XtPointer closure, XtPointer callData) |
1272 | { |
1273 | TextWidget ctx = (TextWidget) closure; |
1274 | Widget tw = (Widget) ctx; |
1275 | Position old_left, pixels = (Position)(intptr_t) callData; |
1276 | XRectangle rect, t_rect; |
1277 | int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; |
1278 | |
1279 | _XawTextPrepareToUpdate(ctx); |
1280 | |
1281 | old_left = ctx->text.margin.left; |
1282 | ctx->text.margin.left -= pixels; |
1283 | if (ctx->text.margin.left > ctx->text.r_margin.left) { |
1284 | ctx->text.margin.left = ctx->text.r_margin.left; |
1285 | pixels = old_left - ctx->text.margin.left; |
1286 | } |
1287 | |
1288 | if (pixels > 0) { |
1289 | rect.width = (unsigned short) pixels + ctx->text.margin.right; |
1290 | rect.x = (short) ctx->core.width - (short) rect.width; |
1291 | rect.y = (short) ctx->text.margin.top; |
1292 | rect.height = (unsigned short) ctx->core.height - rect.y - 2 * s; |
1293 | |
1294 | XCopyArea(XtDisplay(tw)(((tw)->core.screen)->display), XtWindow(tw)((tw)->core.window), XtWindow(tw)((tw)->core.window), ctx->text.gc, |
1295 | pixels + s, (int) rect.y, |
1296 | (unsigned int) rect.x, (unsigned int) ctx->core.height - 2 * s, |
1297 | s, (int) rect.y); |
1298 | |
1299 | PushCopyQueue(ctx, (int) -pixels, 0); |
1300 | } |
1301 | else if (pixels < 0) { |
1302 | rect.x = s; |
1303 | |
1304 | if (ctx->text.vbar != NULL((void*)0)) |
1305 | rect.x += (short) (ctx->text.vbar->core.width + |
1306 | ctx->text.vbar->core.border_width); |
1307 | |
1308 | rect.width = (Position) - pixels; |
1309 | rect.y = ctx->text.margin.top; |
1310 | rect.height = ctx->core.height - rect.y - 2 * s; |
1311 | |
1312 | XCopyArea(XtDisplay(tw)(((tw)->core.screen)->display), XtWindow(tw)((tw)->core.window), XtWindow(tw)((tw)->core.window), ctx->text.gc, |
1313 | (int) rect.x, (int) rect.y, |
1314 | (unsigned int) ctx->core.width - rect.width - 2 * s, |
1315 | (unsigned int) rect.height, |
1316 | (int) rect.x + rect.width, (int) rect.y); |
1317 | |
1318 | PushCopyQueue(ctx, (int) rect.width, 0); |
1319 | |
1320 | /* |
1321 | * Redraw the line overflow marks. |
1322 | */ |
1323 | |
1324 | t_rect.x = ctx->core.width - ctx->text.margin.right - s; |
1325 | t_rect.width = ctx->text.margin.right; |
1326 | t_rect.y = rect.y; |
1327 | t_rect.height = rect.height - 2 * s; |
1328 | |
1329 | SinkClearToBGXawTextSinkClearToBackground(ctx->text.sink, (Position) t_rect.x, (Position) t_rect.y, |
1330 | (Dimension) t_rect.width, (Dimension) t_rect.height); |
1331 | |
1332 | UpdateTextInRectangle(ctx, &t_rect); |
1333 | } |
1334 | |
1335 | /* |
1336 | * Put in the text that just became visible. |
1337 | */ |
1338 | |
1339 | if ( pixels != 0 ) { |
1340 | SinkClearToBGXawTextSinkClearToBackground(ctx->text.sink, (Position) rect.x, (Position) rect.y, |
1341 | (Dimension) rect.width, (Dimension) rect.height); |
1342 | |
1343 | UpdateTextInRectangle(ctx, &rect); |
1344 | } |
1345 | _XawTextExecuteUpdate(ctx); |
1346 | _XawTextSetScrollBars(ctx); |
1347 | } |
1348 | |
1349 | /*ARGSUSED*/ |
1350 | static void |
1351 | HJump(Widget w, XtPointer closure, XtPointer callData) |
1352 | { |
1353 | TextWidget ctx = (TextWidget) closure; |
1354 | float * percent = (float *) callData; |
1355 | Position new_left, old_left = ctx->text.margin.left; |
1356 | |
1357 | long move; /*difference of Positions can be bigger than Position; lint err */ |
1358 | |
1359 | new_left = ctx->text.r_margin.left; |
1360 | new_left -= (Position) (*percent * GetWidestLine(ctx)); |
1361 | move = old_left - new_left; |
1362 | |
1363 | if (abs(move) < (int)ctx->core.width) { |
1364 | HScroll(w, (XtPointer) ctx, (XtPointer) move); |
1365 | return; |
1366 | } |
1367 | _XawTextPrepareToUpdate(ctx); |
1368 | ctx->text.margin.left = new_left; |
1369 | if (XtIsRealized((Widget) ctx)(XtWindowOfObject((Widget) ctx) != 0L)) DisplayTextWindow((Widget) ctx); |
1370 | _XawTextExecuteUpdate(ctx); |
1371 | } |
1372 | |
1373 | /* Function Name: UpdateTextInLine |
1374 | * Description: Updates some text in a given line. |
1375 | * Arguments: ctx - the text widget. |
1376 | * line - the line number (in the line table) of this line. |
1377 | * left, right - left and right pixel offsets of the |
1378 | * area to update. |
1379 | * Returns: none. |
1380 | */ |
1381 | |
1382 | static void |
1383 | UpdateTextInLine(TextWidget ctx, int line, Position left, Position right) |
1384 | { |
1385 | XawTextPosition pos1, pos2; |
1386 | int width, height, local_left, local_width; |
1387 | XawTextLineTableEntry * lt = ctx->text.lt.info + line; |
1388 | |
1389 | if ( ((int)(lt->textWidth + ctx->text.margin.left) < left) || |
1390 | ( ctx->text.margin.left > right ) ) |
1391 | return; /* no need to update. */ |
1392 | |
1393 | local_width = left - ctx->text.margin.left; |
1394 | XawTextSinkFindPosition(ctx->text.sink, lt->position, |
1395 | (int) ctx->text.margin.left, |
1396 | local_width, FALSE0, &pos1, &width, &height); |
1397 | |
1398 | if (right >= (Position) lt->textWidth - ctx->text.margin.left) |
1399 | if ( (IsValidLine(ctx, line + 1)( ((line + 1) == 0) || ((ctx)->text.lt.info[(line + 1)].position != 0) )) && |
1400 | (ctx->text.lt.info[line + 1].position <= ctx->text.lastPos) ) |
1401 | pos2 = SrcScanXawTextSourceScan( ctx->text.source, (lt + 1)->position, XawstPositions, |
1402 | XawsdLeft, 1, TRUE1); |
1403 | else |
1404 | pos2 = GETLASTPOSXawTextSourceScan(ctx->text.source, 0, XawstAll, XawsdRight , 1, 1); |
1405 | else { |
1406 | XawTextPosition t_pos; |
1407 | |
1408 | local_left = ctx->text.margin.left + width; |
1409 | local_width = right - local_left; |
1410 | XawTextSinkFindPosition(ctx->text.sink, pos1, local_left, |
1411 | local_width, FALSE0, &pos2, &width, &height); |
1412 | |
1413 | t_pos = SrcScanXawTextSourceScan( ctx->text.source, pos2, |
1414 | XawstPositions, XawsdRight, 1, TRUE1); |
1415 | if (t_pos < (lt + 1)->position) |
1416 | pos2 = t_pos; |
1417 | } |
1418 | |
1419 | _XawTextNeedsUpdating(ctx, pos1, pos2); |
1420 | } |
1421 | |
1422 | /* |
1423 | * The routine will scroll the displayed text by pixels. If the calldata is |
1424 | * positive, move up; otherwise, move down. |
1425 | */ |
1426 | |
1427 | /*ARGSUSED*/ |
1428 | static void |
1429 | VScroll(Widget w, XtPointer closure, XtPointer callData) |
1430 | { |
1431 | TextWidget ctx = (TextWidget)closure; |
1432 | int height, nlines, lines = (intptr_t) callData; |
1433 | |
1434 | height = ctx->core.height - VMargins(ctx)( (ctx)->text.margin.top + (ctx)->text.margin.bottom ); |
1435 | if (height < 1) |
1436 | height = 1; |
1437 | nlines = (int) (lines * (int) ctx->text.lt.lines) / height; |
1438 | #ifdef XAW_ARROW_SCROLLBARS |
1439 | if (nlines == 0 && lines != 0) |
1440 | nlines = lines > 0 ? 1 : -1; |
1441 | #endif |
1442 | _XawTextPrepareToUpdate(ctx); |
1443 | _XawTextVScroll(ctx, nlines); |
1444 | _XawTextExecuteUpdate(ctx); |
1445 | } |
1446 | |
1447 | /* |
1448 | * The routine "thumbs" the displayed text. Thumbing means reposition the |
1449 | * displayed view of the source to a new position determined by a fraction |
1450 | * of the way from beginning to end. Ideally, this should be determined by |
1451 | * the number of displayable lines in the source. This routine does it as a |
1452 | * fraction of the first position and last position and then normalizes to |
1453 | * the start of the line containing the position. |
1454 | * |
1455 | * BUG/deficiency: The normalize to line portion of this routine will |
1456 | * cause thumbing to always position to the start of the source. |
1457 | */ |
1458 | |
1459 | /*ARGSUSED*/ |
1460 | static void |
1461 | VJump(Widget w, XtPointer closure, XtPointer callData) |
1462 | { |
1463 | float * percent = (float *) callData; |
1464 | TextWidget ctx = (TextWidget)closure; |
1465 | XawTextPosition position, old_top, old_bot; |
1466 | XawTextLineTable * lt = &(ctx->text.lt); |
1467 | |
1468 | _XawTextPrepareToUpdate(ctx); |
1469 | old_top = lt->top; |
1470 | if ( (lt->lines > 0) && (IsValidLine(ctx, lt->lines - 1)( ((lt->lines - 1) == 0) || ((ctx)->text.lt.info[(lt-> lines - 1)].position != 0) )) ) |
1471 | old_bot = lt->info[lt->lines - 1].position; |
1472 | else |
1473 | old_bot = ctx->text.lastPos; |
1474 | |
1475 | position = (long) (*percent * (float) ctx->text.lastPos); |
1476 | position= SrcScanXawTextSourceScan(ctx->text.source, position, XawstEOL, XawsdLeft, 1, FALSE0); |
1477 | if ( (position >= old_top) && (position <= old_bot) ) { |
1478 | int line = 0; |
1479 | for (;(line < lt->lines) && (position > lt->info[line].position) ; line++); |
1480 | _XawTextVScroll(ctx, line); |
1481 | } |
1482 | else { |
1483 | XawTextPosition new_bot; |
1484 | _XawTextBuildLineTable(ctx, position, FALSE0); |
1485 | new_bot = IsValidLine(ctx, lt->lines-1)( ((lt->lines-1) == 0) || ((ctx)->text.lt.info[(lt-> lines-1)].position != 0) ) ? lt->info[lt->lines-1].position |
1486 | : ctx->text.lastPos; |
1487 | |
1488 | if ((old_top >= lt->top) && (old_top <= new_bot)) { |
1489 | int line = 0; |
1490 | for (;(line < lt->lines) && (old_top > lt->info[line].position); line++); |
1491 | _XawTextBuildLineTable(ctx, old_top, FALSE0); |
1492 | _XawTextVScroll(ctx, -line); |
1493 | } |
1494 | else |
1495 | DisplayTextWindow( (Widget) ctx); |
1496 | } |
1497 | _XawTextExecuteUpdate(ctx); |
1498 | } |
1499 | |
1500 | static Boolean |
1501 | MatchSelection(Atom selection, XawTextSelection *s) |
1502 | { |
1503 | Atom *match; |
1504 | int count; |
1505 | |
1506 | for (count = 0, match = s->selections; count < s->atom_count; match++, count++) |
1507 | if (*match == selection) |
1508 | return True1; |
1509 | return False0; |
1510 | } |
1511 | |
1512 | static Boolean |
1513 | ConvertSelection(Widget w, Atom *selection, Atom *target, Atom *type, |
1514 | XtPointer *value, unsigned long *length, int *format) |
1515 | { |
1516 | Display* d = XtDisplay(w)(((w)->core.screen)->display); |
1517 | TextWidget ctx = (TextWidget)w; |
1518 | Widget src = ctx->text.source; |
1519 | XawTextEditType edit_mode; |
1520 | Arg args[1]; |
1521 | |
1522 | XawTextSelectionSalt *salt = NULL((void*)0); |
1523 | XawTextSelection *s; |
1524 | |
1525 | if (*target == XA_TARGETS(d)XmuInternAtom(d, _XA_TARGETS)) { |
1526 | Atom* targetP, * std_targets; |
1527 | unsigned long std_length; |
1528 | |
1529 | if ( SrcCvtSelXawTextSourceConvertSelection(src, selection, target, type, value, length, format) ) |
1530 | return True1; |
1531 | |
1532 | XmuConvertStandardSelection(w, ctx->text.time, selection, |
1533 | target, type, (XPointer*)&std_targets, |
1534 | &std_length, format); |
1535 | |
1536 | *value = XtMalloc((unsigned) sizeof(Atom)*(std_length + 7)); |
1537 | targetP = *(Atom**)value; |
1538 | *length = std_length + 6; |
1539 | *targetP++ = XA_STRING((Atom) 31); |
1540 | *targetP++ = XA_TEXT(d)XmuInternAtom(d, _XA_TEXT); |
1541 | *targetP++ = XA_COMPOUND_TEXT(d)XmuInternAtom(d, _XA_COMPOUND_TEXT); |
1542 | *targetP++ = XA_LENGTH(d)XmuInternAtom(d, _XA_LENGTH); |
1543 | *targetP++ = XA_LIST_LENGTH(d)XmuInternAtom(d, _XA_LIST_LENGTH); |
1544 | *targetP++ = XA_CHARACTER_POSITION(d)XmuInternAtom(d, _XA_CHARACTER_POSITION); |
1545 | |
1546 | XtSetArg(args[0], XtNeditType,&edit_mode)((void)( (args[0]).name = (((char*)&XtStrings[185])), (args [0]).value = (XtArgVal)(&edit_mode) )); |
1547 | XtGetValues(src, args, ONE((Cardinal)1)); |
1548 | |
1549 | if (edit_mode == XawtextEdit) { |
1550 | *targetP++ = XA_DELETE(d)XmuInternAtom(d, _XA_DELETE); |
1551 | (*length)++; |
1552 | } |
1553 | (void) memmove((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length)__builtin___memmove_chk ((char*)targetP, (char*)std_targets, sizeof (Atom)*std_length, __builtin_object_size ((char*)targetP, 0)); |
1554 | XtFree((char*)std_targets); |
1555 | *type = XA_ATOM((Atom) 4); |
1556 | *format = 32; |
1557 | return True1; |
1558 | } |
1559 | |
1560 | if ( SrcCvtSelXawTextSourceConvertSelection(src, selection, target, type, value, length, format) ) |
1561 | return True1; |
1562 | |
1563 | if (MatchSelection (*selection, &ctx->text.s)) |
1564 | s = &ctx->text.s; |
1565 | else |
1566 | { |
1567 | for (salt = ctx->text.salt; salt; salt = salt->next) |
1568 | if (MatchSelection (*selection, &salt->s)) |
1569 | break; |
1570 | if (!salt) |
1571 | return False0; |
1572 | s = &salt->s; |
1573 | } |
1574 | if (*target == XA_STRING((Atom) 31) || |
1575 | *target == XA_TEXT(d)XmuInternAtom(d, _XA_TEXT) || |
1576 | *target == XA_COMPOUND_TEXT(d)XmuInternAtom(d, _XA_COMPOUND_TEXT)) { |
1577 | if (*target == XA_TEXT(d)XmuInternAtom(d, _XA_TEXT)) { |
1578 | #ifdef XAW_INTERNATIONALIZATION1 |
1579 | if (_XawTextFormat(ctx) == XawFmtWide) |
1580 | *type = XA_COMPOUND_TEXT(d)XmuInternAtom(d, _XA_COMPOUND_TEXT); |
1581 | else |
1582 | #endif |
1583 | *type = XA_STRING((Atom) 31); |
1584 | } else { |
1585 | *type = *target; |
1586 | } |
1587 | /* |
1588 | * If salt is True, the salt->contents stores CT string, |
1589 | * its length is measured in bytes. |
1590 | * Refer to _XawTextSaltAwaySelection(). |
1591 | * |
1592 | * by Li Yuhong, Mar. 20, 1991. |
1593 | */ |
1594 | if (!salt) { |
1595 | *value = _XawTextGetSTRING(ctx, s->left, s->right); |
1596 | #ifdef XAW_INTERNATIONALIZATION1 |
1597 | if (_XawTextFormat(ctx) == XawFmtWide) { |
1598 | XTextProperty textprop; |
1599 | if (XwcTextListToTextProperty(d, (wchar_t **)value, 1, |
1600 | XCompoundTextStyle, &textprop) |
1601 | < Success0) { |
1602 | XtFree(*value); |
1603 | return False0; |
1604 | } |
1605 | XtFree(*value); |
1606 | *value = (XtPointer)textprop.value; |
1607 | *length = textprop.nitems; |
1608 | } else |
1609 | #endif |
1610 | { |
1611 | *length = strlen(*value); |
1612 | } |
1613 | } else { |
1614 | *value = XtMalloc((salt->length + 1) * sizeof(unsigned char)); |
1615 | strcpy (*value, salt->contents)__builtin___strcpy_chk (*value, salt->contents, __builtin_object_size (*value, 2 > 1 ? 1 : 0)); |
1616 | *length = salt->length; |
1617 | } |
1618 | #ifdef XAW_INTERNATIONALIZATION1 |
1619 | if (_XawTextFormat(ctx) == XawFmtWide && *type == XA_STRING((Atom) 31)) { |
1620 | XTextProperty textprop; |
1621 | wchar_t **wlist; |
1622 | int count; |
1623 | textprop.encoding = XA_COMPOUND_TEXT(d)XmuInternAtom(d, _XA_COMPOUND_TEXT); |
1624 | textprop.value = (unsigned char *)*value; |
1625 | textprop.nitems = strlen(*value); |
1626 | textprop.format = 8; |
1627 | if (XwcTextPropertyToTextList(d, &textprop, (wchar_t ***)&wlist, &count) |
1628 | < Success0) { |
1629 | XtFree(*value); |
1630 | return False0; |
1631 | } |
1632 | XtFree(*value); |
1633 | if (XwcTextListToTextProperty( d, (wchar_t **)wlist, 1, |
1634 | XStringStyle, &textprop) < Success0) { |
1635 | XwcFreeStringList( (wchar_t**) wlist ); |
1636 | return False0; |
1637 | } |
1638 | *value = (XtPointer) textprop.value; |
1639 | *length = textprop.nitems; |
1640 | XwcFreeStringList( (wchar_t**) wlist ); |
1641 | } |
1642 | #endif |
1643 | *format = 8; |
1644 | return True1; |
1645 | } |
1646 | |
1647 | if ( (*target == XA_LIST_LENGTH(d)XmuInternAtom(d, _XA_LIST_LENGTH)) || (*target == XA_LENGTH(d)XmuInternAtom(d, _XA_LENGTH)) ) { |
1648 | long * temp; |
1649 | |
1650 | temp = (long *) XtMalloc( (unsigned) sizeof(long) ); |
1651 | if (*target == XA_LIST_LENGTH(d)XmuInternAtom(d, _XA_LIST_LENGTH)) |
1652 | *temp = 1L; |
1653 | else /* *target == XA_LENGTH(d) */ |
1654 | *temp = (long) (s->right - s->left); |
1655 | |
1656 | *value = (XPointer) temp; |
1657 | *type = XA_INTEGER((Atom) 19); |
1658 | *length = 1L; |
1659 | *format = 32; |
1660 | return True1; |
1661 | } |
1662 | |
1663 | if (*target == XA_CHARACTER_POSITION(d)XmuInternAtom(d, _XA_CHARACTER_POSITION)) { |
1664 | long * temp; |
1665 | |
1666 | temp = (long *) XtMalloc( (unsigned)( 2 * sizeof(long) ) ); |
1667 | temp[0] = (long) (s->left + 1); |
1668 | temp[1] = s->right; |
1669 | *value = (XPointer) temp; |
1670 | *type = XA_SPAN(d)XmuInternAtom(d, _XA_SPAN); |
1671 | *length = 2L; |
1672 | *format = 32; |
1673 | return True1; |
1674 | } |
1675 | |
1676 | if (*target == XA_DELETE(d)XmuInternAtom(d, _XA_DELETE)) { |
1677 | if (!salt) |
1678 | _XawTextZapSelection( ctx, (XEvent *) NULL((void*)0), TRUE1); |
1679 | *value = NULL((void*)0); |
1680 | *type = XA_NULL(d)XmuInternAtom(d, _XA_NULL); |
1681 | *length = 0; |
1682 | *format = 32; |
1683 | return True1; |
1684 | } |
1685 | |
1686 | if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type, |
1687 | (XPointer *)value, length, format)) |
1688 | return True1; |
1689 | |
1690 | /* else */ |
1691 | return False0; |
1692 | } |
1693 | |
1694 | /* Function Name: GetCutBuffferNumber |
1695 | * Description: Returns the number of the cut buffer. |
1696 | * Arguments: atom - the atom to check. |
1697 | * Returns: the number of the cut buffer representing this atom or |
1698 | * NOT_A_CUT_BUFFER. |
1699 | */ |
1700 | |
1701 | #define NOT_A_CUT_BUFFER-1 -1 |
1702 | |
1703 | static int |
1704 | GetCutBufferNumber(Atom atom) |
1705 | { |
1706 | if (atom == XA_CUT_BUFFER0((Atom) 9)) return(0); |
1707 | if (atom == XA_CUT_BUFFER1((Atom) 10)) return(1); |
1708 | if (atom == XA_CUT_BUFFER2((Atom) 11)) return(2); |
1709 | if (atom == XA_CUT_BUFFER3((Atom) 12)) return(3); |
1710 | if (atom == XA_CUT_BUFFER4((Atom) 13)) return(4); |
1711 | if (atom == XA_CUT_BUFFER5((Atom) 14)) return(5); |
1712 | if (atom == XA_CUT_BUFFER6((Atom) 15)) return(6); |
1713 | if (atom == XA_CUT_BUFFER7((Atom) 16)) return(7); |
1714 | return(NOT_A_CUT_BUFFER-1); |
1715 | } |
1716 | |
1717 | static void |
1718 | LoseSelection(Widget w, Atom *selection) |
1719 | { |
1720 | TextWidget ctx = (TextWidget) w; |
1721 | Atom* atomP; |
1722 | int i; |
1723 | XawTextSelectionSalt *salt, *prevSalt, *nextSalt; |
1724 | |
1725 | _XawTextPrepareToUpdate(ctx); |
1726 | |
1727 | atomP = ctx->text.s.selections; |
1728 | for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++) |
1729 | if ( (*selection == *atomP) || |
1730 | (GetCutBufferNumber(*atomP) != NOT_A_CUT_BUFFER-1) )/* is a cut buffer */ |
1731 | *atomP = (Atom)0; |
1732 | |
1733 | while (ctx->text.s.atom_count && |
1734 | ctx->text.s.selections[ctx->text.s.atom_count-1] == 0) |
1735 | ctx->text.s.atom_count--; |
1736 | |
1737 | /* |
1738 | * Must walk the selection list in opposite order from UnsetSelection. |
1739 | */ |
1740 | |
1741 | atomP = ctx->text.s.selections; |
1742 | for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++) |
1743 | if (*atomP == (Atom)0) { |
1744 | *atomP = ctx->text.s.selections[--ctx->text.s.atom_count]; |
1745 | while (ctx->text.s.atom_count && |
1746 | ctx->text.s.selections[ctx->text.s.atom_count-1] == 0) |
1747 | ctx->text.s.atom_count--; |
1748 | } |
1749 | |
1750 | if (ctx->text.s.atom_count == 0) |
1751 | ModifySelection(ctx, ctx->text.insertPos, ctx->text.insertPos); |
1752 | |
1753 | if (ctx->text.old_insert >= 0) /* Update in progress. */ |
1754 | _XawTextExecuteUpdate(ctx); |
1755 | |
1756 | prevSalt = 0; |
1757 | for (salt = ctx->text.salt; salt; salt = nextSalt) |
1758 | { |
1759 | atomP = salt->s.selections; |
1760 | nextSalt = salt->next; |
1761 | for (i = 0 ; i < salt->s.atom_count; i++, atomP++) |
1762 | if (*selection == *atomP) |
1763 | *atomP = (Atom)0; |
1764 | |
1765 | while (salt->s.atom_count && |
1766 | salt->s.selections[salt->s.atom_count-1] == 0) |
1767 | { |
1768 | salt->s.atom_count--; |
1769 | } |
1770 | |
1771 | /* |
1772 | * Must walk the selection list in opposite order from UnsetSelection. |
1773 | */ |
1774 | |
1775 | atomP = salt->s.selections; |
1776 | for (i = 0 ; i < salt->s.atom_count; i++, atomP++) |
1777 | if (*atomP == (Atom)0) |
1778 | { |
1779 | *atomP = salt->s.selections[--salt->s.atom_count]; |
1780 | while (salt->s.atom_count && |
1781 | salt->s.selections[salt->s.atom_count-1] == 0) |
1782 | salt->s.atom_count--; |
1783 | } |
1784 | if (salt->s.atom_count == 0) |
1785 | { |
1786 | XtFree ((char *) salt->s.selections); |
1787 | XtFree (salt->contents); |
1788 | if (prevSalt) |
1789 | prevSalt->next = nextSalt; |
1790 | else |
1791 | ctx->text.salt = nextSalt; |
1792 | XtFree ((char *) salt); |
1793 | } |
1794 | else |
1795 | prevSalt = salt; |
1796 | } |
1797 | } |
1798 | |
1799 | void |
1800 | _XawTextSaltAwaySelection(TextWidget ctx, Atom *selections, int num_atoms) |
1801 | { |
1802 | XawTextSelectionSalt *salt; |
1803 | int i, j; |
1804 | |
1805 | for (i = 0; i < num_atoms; i++) |
1806 | LoseSelection ((Widget) ctx, selections + i); |
1807 | if (num_atoms == 0) |
1808 | return; |
1809 | salt = (XawTextSelectionSalt *) |
1810 | XtMalloc( (unsigned) sizeof(XawTextSelectionSalt) ); |
1811 | if (!salt) |
1812 | return; |
1813 | salt->s.selections = (Atom *) |
1814 | XtMalloc( (unsigned) ( num_atoms * sizeof (Atom) ) ); |
1815 | if (!salt->s.selections) |
1816 | { |
1817 | XtFree ((char *) salt); |
1818 | return; |
1819 | } |
1820 | salt->s.left = ctx->text.s.left; |
1821 | salt->s.right = ctx->text.s.right; |
1822 | salt->s.type = ctx->text.s.type; |
1823 | salt->contents = _XawTextGetSTRING(ctx, ctx->text.s.left, ctx->text.s.right); |
1824 | #ifdef XAW_INTERNATIONALIZATION1 |
1825 | if (_XawTextFormat(ctx) == XawFmtWide) { |
1826 | XTextProperty textprop; |
1827 | if (XwcTextListToTextProperty(XtDisplay((Widget)ctx)((((Widget)ctx)->core.screen)->display), |
1828 | (wchar_t**)(&(salt->contents)), 1, XCompoundTextStyle, |
1829 | &textprop) < Success0) { |
1830 | XtFree(salt->contents); |
1831 | salt->length = 0; |
1832 | return; |
1833 | } |
1834 | XtFree(salt->contents); |
1835 | salt->contents = (char *)textprop.value; |
1836 | salt->length = textprop.nitems; |
1837 | } else |
1838 | #endif |
1839 | salt->length = strlen (salt->contents); |
1840 | salt->next = ctx->text.salt; |
1841 | ctx->text.salt = salt; |
1842 | j = 0; |
1843 | for (i = 0; i < num_atoms; i++) |
1844 | { |
1845 | if (GetCutBufferNumber (selections[i]) == NOT_A_CUT_BUFFER-1) |
1846 | { |
1847 | salt->s.selections[j++] = selections[i]; |
1848 | XtOwnSelection ((Widget) ctx, selections[i], ctx->text.time, |
1849 | ConvertSelection, LoseSelection, (XtSelectionDoneProc)NULL((void*)0)); |
1850 | } |
1851 | } |
1852 | salt->s.atom_count = j; |
1853 | } |
1854 | |
1855 | static void |
1856 | _SetSelection(TextWidget ctx, XawTextPosition left, XawTextPosition right, |
1857 | Atom *selections, Cardinal count) |
1858 | { |
1859 | XawTextPosition pos; |
1860 | |
1861 | if (left < ctx->text.s.left) { |
1862 | pos = Min(right, ctx->text.s.left)(((right) < (ctx->text.s.left)) ? (right) : (ctx->text .s.left)); |
1863 | _XawTextNeedsUpdating(ctx, left, pos); |
1864 | } |
1865 | if (left > ctx->text.s.left) { |
1866 | pos = Min(left, ctx->text.s.right)(((left) < (ctx->text.s.right)) ? (left) : (ctx->text .s.right)); |
1867 | _XawTextNeedsUpdating(ctx, ctx->text.s.left, pos); |
1868 | } |
1869 | if (right < ctx->text.s.right) { |
1870 | pos = Max(right, ctx->text.s.left)(((right) > (ctx->text.s.left)) ? (right) : (ctx->text .s.left)); |
1871 | _XawTextNeedsUpdating(ctx, pos, ctx->text.s.right); |
1872 | } |
1873 | if (right > ctx->text.s.right) { |
1874 | pos = Max(left, ctx->text.s.right)(((left) > (ctx->text.s.right)) ? (left) : (ctx->text .s.right)); |
1875 | _XawTextNeedsUpdating(ctx, pos, right); |
1876 | } |
1877 | |
1878 | ctx->text.s.left = left; |
1879 | ctx->text.s.right = right; |
1880 | |
1881 | SrcSetSelectionXawTextSourceSetSelection(ctx->text.source, left, right, |
1882 | (count == 0) ? None0L : selections[0]); |
1883 | |
1884 | if (left < right) { |
1885 | Widget w = (Widget) ctx; |
1886 | int buffer; |
1887 | |
1888 | while (count) { |
1889 | Atom selection = selections[--count]; |
1890 | |
1891 | if ((buffer = GetCutBufferNumber(selection)) != NOT_A_CUT_BUFFER-1) { |
1892 | |
1893 | unsigned char *ptr, *tptr; |
1894 | unsigned int amount, max_len = MAX_CUT_LEN(XtDisplay(w))(XMaxRequestSize((((w)->core.screen)->display)) - 64); |
1895 | unsigned long len; |
1896 | |
1897 | tptr= ptr= (unsigned char *) _XawTextGetSTRING(ctx, ctx->text.s.left, |
1898 | ctx->text.s.right); |
1899 | #ifdef XAW_INTERNATIONALIZATION1 |
1900 | if (_XawTextFormat(ctx) == XawFmtWide) { |
1901 | /* |
1902 | * Only XA_STRING(Latin 1) is allowed in CUT_BUFFER, |
1903 | * so we get it from wchar string, then free the wchar string. |
1904 | */ |
1905 | XTextProperty textprop; |
1906 | if (XwcTextListToTextProperty(XtDisplay(w)(((w)->core.screen)->display), (wchar_t**)&ptr, 1, |
1907 | XStringStyle, &textprop) < Success0) { |
1908 | XtFree((char *)ptr); |
1909 | return; |
1910 | } |
1911 | XtFree((char *)ptr); |
1912 | tptr = ptr = textprop.value; |
1913 | } |
1914 | #endif |
1915 | if (buffer == 0) { |
1916 | _CreateCutBuffers(XtDisplay(w)(((w)->core.screen)->display)); |
1917 | XRotateBuffers(XtDisplay(w)(((w)->core.screen)->display), 1); |
1918 | } |
1919 | amount = Min ( (len = strlen((char *)ptr)), max_len)((((len = strlen((char *)ptr))) < (max_len)) ? ((len = strlen ((char *)ptr))) : (max_len)); |
1920 | XChangeProperty(XtDisplay(w)(((w)->core.screen)->display), RootWindow(XtDisplay(w), 0)((&((_XPrivDisplay)((((w)->core.screen)->display))) ->screens[0])->root), selection, |
1921 | XA_STRING((Atom) 31), 8, PropModeReplace0, ptr, amount); |
1922 | |
1923 | while (len > max_len) { |
1924 | len -= max_len; |
1925 | tptr += max_len; |
1926 | amount = Min (len, max_len)(((len) < (max_len)) ? (len) : (max_len)); |
1927 | XChangeProperty(XtDisplay(w)(((w)->core.screen)->display), RootWindow(XtDisplay(w), 0)((&((_XPrivDisplay)((((w)->core.screen)->display))) ->screens[0])->root), |
1928 | selection, XA_STRING((Atom) 31), 8, PropModeAppend2, |
1929 | tptr, amount); |
1930 | } |
1931 | XtFree ((char *)ptr); |
1932 | } |
1933 | else /* This is a real selection */ |
1934 | XtOwnSelection(w, selection, ctx->text.time, ConvertSelection, |
1935 | LoseSelection, (XtSelectionDoneProc)NULL((void*)0)); |
1936 | } |
1937 | } |
1938 | else |
1939 | XawTextUnsetSelection((Widget)ctx); |
1940 | } |
1941 | |
1942 | /* |
1943 | * This internal routine deletes the text from pos1 to pos2 in a source and |
1944 | * then inserts, at pos1, the text that was passed. As a side effect it |
1945 | * "invalidates" that portion of the displayed text (if any). |
1946 | * |
1947 | * NOTE: It is illegal to call this routine unless there is a valid line table! |
1948 | */ |
1949 | |
1950 | int |
1951 | _XawTextReplace (TextWidget ctx, XawTextPosition pos1, XawTextPosition pos2, |
1952 | XawTextBlock *text) |
1953 | { |
1954 | int i, line1, delta, error; |
1955 | XawTextPosition updateFrom, updateTo; |
1956 | Widget src = ctx->text.source; |
1957 | XawTextEditType edit_mode; |
1958 | Arg args[1]; |
1959 | Boolean tmp = ctx->text.update_disabled; |
1960 | |
1961 | ctx->text.update_disabled = True1; /* No redisplay during replacement. */ |
1962 | |
1963 | /* |
1964 | * The insertPos may not always be set to the right spot in XawtextAppend |
1965 | */ |
1966 | |
1967 | XtSetArg(args[0], XtNeditType, &edit_mode)((void)( (args[0]).name = (((char*)&XtStrings[185])), (args [0]).value = (XtArgVal)(&edit_mode) )); |
1968 | XtGetValues(src, args, ONE((Cardinal)1)); |
1969 | |
1970 | if ((pos1 == ctx->text.insertPos) && (edit_mode == XawtextAppend)) { |
1971 | ctx->text.insertPos = ctx->text.lastPos; |
1972 | pos2 = SrcScanXawTextSourceScan(src, ctx->text.insertPos, XawstPositions, XawsdRight, |
1973 | (int)(ctx->text.insertPos - pos1), (Boolean)TRUE1); |
1974 | pos1 = ctx->text.insertPos; |
1975 | if ( (pos1 == pos2) && (text->length == 0) ) { |
1976 | ctx->text.update_disabled = FALSE0; /* rearm redisplay. */ |
1977 | return( XawEditError1 ); |
1978 | } |
1979 | } |
1980 | |
1981 | updateFrom = SrcScanXawTextSourceScan(src, pos1, XawstWhiteSpace, XawsdLeft, 1, FALSE0); |
1982 | updateFrom = Max(updateFrom, ctx->text.lt.top)(((updateFrom) > (ctx->text.lt.top)) ? (updateFrom) : ( ctx->text.lt.top)); |
1983 | |
1984 | line1 = LineForPosition(ctx, updateFrom); |
1985 | if ( (error = SrcReplaceXawTextSourceReplace(src, pos1, pos2, text)) != 0) { |
1986 | ctx->text.update_disabled = tmp; /* restore redisplay */ |
1987 | return(error); |
1988 | } |
1989 | |
1990 | XawTextUnsetSelection((Widget)ctx); |
1991 | |
1992 | ctx->text.lastPos = GETLASTPOSXawTextSourceScan(ctx->text.source, 0, XawstAll, XawsdRight , 1, 1); |
1993 | if (ctx->text.lt.top >= ctx->text.lastPos) { |
1994 | _XawTextBuildLineTable(ctx, ctx->text.lastPos, FALSE0); |
1995 | ClearWindow( (Widget) ctx); |
1996 | ctx->text.update_disabled = tmp; /* restore redisplay */ |
1997 | return(0); /* Things are fine. */ |
1998 | } |
1999 | |
2000 | ctx->text.single_char = (text->length <= 1 && pos2 - pos1 <= 1); |
2001 | |
2002 | delta = text->length - (pos2 - pos1); |
2003 | |
2004 | if (delta < ctx->text.lastPos) { |
2005 | for (pos2 += delta, i = 0; i < ctx->text.numranges; i++) { |
Value stored to 'pos2' is never read | |
2006 | if (ctx->text.updateFrom[i] > pos1) |
2007 | ctx->text.updateFrom[i] += delta; |
2008 | if (ctx->text.updateTo[i] >= pos1) |
2009 | ctx->text.updateTo[i] += delta; |
2010 | } |
2011 | } |
2012 | |
2013 | /* |
2014 | * fixup all current line table entries to reflect edit. |
2015 | * %%% it is not legal to do arithmetic on positions. |
2016 | * using Scan would be more proper. |
2017 | */ |
2018 | if (delta != 0) { |
2019 | XawTextLineTableEntry *lineP; |
2020 | i = LineForPosition(ctx, pos1) + 1; |
2021 | for (lineP = ctx->text.lt.info + i; i <= ctx->text.lt.lines; i++, lineP++) |
2022 | lineP->position += delta; |
2023 | } |
2024 | |
2025 | /* |
2026 | * Now process the line table and fixup in case edits caused |
2027 | * changes in line breaks. If we are breaking on word boundaries, |
2028 | * this code checks for moving words to and from lines. |
2029 | */ |
2030 | |
2031 | if (IsPositionVisible(ctx, updateFrom)(updateFrom >= ctx->text.lt.info[0].position && updateFrom < ctx->text.lt.info[ctx->text.lt.lines]. position)) { |
2032 | updateTo = _BuildLineTable(ctx, |
2033 | ctx->text.lt.info[line1].position, pos1, line1); |
2034 | _XawTextNeedsUpdating(ctx, updateFrom, updateTo); |
2035 | } |
2036 | |
2037 | ctx->text.update_disabled = tmp; /* restore redisplay */ |
2038 | return(0); /* Things are fine. */ |
2039 | } |
2040 | |
2041 | /* |
2042 | * This routine will display text between two arbitrary source positions. |
2043 | * In the event that this span contains highlighted text for the selection, |
2044 | * only that portion will be displayed highlighted. |
2045 | * |
2046 | * NOTE: it is illegal to call this routine unless there |
2047 | * is a valid line table! |
2048 | */ |
2049 | |
2050 | static void |
2051 | DisplayText(Widget w, XawTextPosition pos1, XawTextPosition pos2) |
2052 | { |
2053 | TextWidget ctx = (TextWidget)w; |
2054 | Position x, y; |
2055 | int height, line, i, lastPos = ctx->text.lastPos; |
2056 | XawTextPosition startPos, endPos; |
2057 | Boolean clear_eol, done_painting; |
2058 | Dimension s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; |
2059 | |
2060 | pos1 = (pos1 < ctx->text.lt.top) ? ctx->text.lt.top : pos1; |
2061 | pos2 = FindGoodPosition(ctx, pos2); |
2062 | if ( (pos1 >= pos2) || !LineAndXYForPosition(ctx, pos1, &line, &x, &y) ) |
2063 | return; /* line not visible, or pos1 >= pos2. */ |
2064 | |
2065 | for ( startPos = pos1, i = line; IsValidLine(ctx, i)( ((i) == 0) || ((ctx)->text.lt.info[(i)].position != 0) ) && |
2066 | (i < ctx->text.lt.lines) ; i++) { |
2067 | |
2068 | |
2069 | if ( (endPos = ctx->text.lt.info[i + 1].position) > pos2 ) { |
2070 | clear_eol = ((endPos = pos2) >= lastPos); |
2071 | done_painting = (!clear_eol || ctx->text.single_char); |
2072 | } |
2073 | else { |
2074 | clear_eol = TRUE1; |
2075 | done_painting = FALSE0; |
2076 | } |
2077 | |
2078 | height = ctx->text.lt.info[i + 1].y - ctx->text.lt.info[i].y - s + 1; |
2079 | |
2080 | if ( (endPos > startPos) ) { |
2081 | |
2082 | /* note to self: _ShadowSurroundedBox() hacks are in here */ |
2083 | |
2084 | if ( (x == (Position) ctx->text.margin.left) && (x > 0) ) |
2085 | { |
2086 | SinkClearToBGXawTextSinkClearToBackground (ctx->text.sink, |
2087 | (Position) s, y, |
2088 | (Dimension) ctx->text.margin.left, (Dimension)height); |
2089 | _ShadowSurroundedBox((Widget)ctx, (ThreeDWidget)ctx->text.threeD, |
2090 | 0, 0, ctx->core.width, ctx->core.height, |
2091 | ((ThreeDWidget)ctx->text.threeD)->threeD.relief, |
2092 | False0); |
2093 | } |
2094 | |
2095 | if ( (startPos >= ctx->text.s.right) || (endPos <= ctx->text.s.left) ) |
2096 | XawTextSinkDisplayText(ctx->text.sink, x, y, startPos, endPos, FALSE0); |
2097 | else if ((startPos >= ctx->text.s.left) && (endPos <= ctx->text.s.right)) |
2098 | XawTextSinkDisplayText(ctx->text.sink, x, y, startPos, endPos, TRUE1); |
2099 | else { |
2100 | DisplayText(w, startPos, ctx->text.s.left); |
2101 | DisplayText(w, Max(startPos, ctx->text.s.left)(((startPos) > (ctx->text.s.left)) ? (startPos) : (ctx-> text.s.left)), |
2102 | Min(endPos, ctx->text.s.right)(((endPos) < (ctx->text.s.right)) ? (endPos) : (ctx-> text.s.right))); |
2103 | DisplayText(w, ctx->text.s.right, endPos); |
2104 | } |
2105 | } |
2106 | startPos = endPos; |
2107 | if (clear_eol) { |
2108 | Position myx = ctx->text.lt.info[i].textWidth + ctx->text.margin.left; |
2109 | |
2110 | SinkClearToBGXawTextSinkClearToBackground(ctx->text.sink, |
2111 | (Position) myx, |
2112 | (Position) y, w->core.width - myx/* - 2 * s*/, |
2113 | (Dimension) height); |
2114 | _ShadowSurroundedBox((Widget)ctx, (ThreeDWidget)ctx->text.threeD, |
2115 | 0, 0, ctx->core.width, ctx->core.height, |
2116 | ((ThreeDWidget)ctx->text.threeD)->threeD.relief, |
2117 | False0); |
2118 | |
2119 | /* |
2120 | * We only get here if single character is true, and we need |
2121 | * to clear to the end of the screen. We know that since there |
2122 | * was only one character deleted that this is the same |
2123 | * as clearing an extra line, so we do this, and are done. |
2124 | * |
2125 | * This a performance hack, and a pretty gross one, but it works. |
2126 | * |
2127 | * Chris Peterson 11/13/89. |
2128 | */ |
2129 | |
2130 | if (done_painting) { |
2131 | y += height; |
2132 | SinkClearToBGXawTextSinkClearToBackground(ctx->text.sink, |
2133 | (Position) ctx->text.margin.left, (Position) y, |
2134 | w->core.width - ctx->text.margin.left/* - 2 * s*/, |
2135 | (Dimension) Min(height, ctx->core.height - 2 * s - y)(((height) < (ctx->core.height - 2 * s - y)) ? (height) : (ctx->core.height - 2 * s - y))); |
2136 | _ShadowSurroundedBox((Widget)ctx, (ThreeDWidget)ctx->text.threeD, |
2137 | 0, 0, ctx->core.width, ctx->core.height, |
2138 | ((ThreeDWidget)ctx->text.threeD)->threeD.relief, |
2139 | False0); |
2140 | |
2141 | break; /* set single_char to FALSE and return. */ |
2142 | } |
2143 | } |
2144 | |
2145 | x = (Position) ctx->text.margin.left; |
2146 | y = ctx->text.lt.info[i + 1].y; |
2147 | if ( done_painting |
2148 | || (y >= (int)(ctx->core.height - ctx->text.margin.bottom)) ) |
2149 | break; |
2150 | } |
2151 | ctx->text.single_char = FALSE0; |
2152 | } |
2153 | |
2154 | /* |
2155 | * This routine implements multi-click selection in a hardwired manner. |
2156 | * It supports multi-click entity cycling (char, word, line, file) and mouse |
2157 | * motion adjustment of the selected entitie (i.e. select a word then, with |
2158 | * button still down, adjust wich word you really meant by moving the mouse). |
2159 | * [NOTE: This routine is to be replaced by a set of procedures that |
2160 | * will allows clients to implements a wide class of draw through and |
2161 | * multi-click selection user interfaces.] |
2162 | */ |
2163 | |
2164 | static void |
2165 | DoSelection (TextWidget ctx, XawTextPosition pos, Time time, Boolean motion) |
2166 | { |
2167 | XawTextPosition newLeft, newRight; |
2168 | XawTextSelectType newType, *sarray; |
2169 | Widget src = ctx->text.source; |
2170 | |
2171 | if (motion) |
2172 | newType = ctx->text.s.type; |
2173 | else { |
2174 | if ( (labs((long) time - (long) ctx->text.lasttime) < MULTI_CLICK_TIME500L) && |
2175 | ((pos >= ctx->text.s.left) && (pos <= ctx->text.s.right))) { |
2176 | sarray = ctx->text.sarray; |
2177 | for (;*sarray != XawselectNull && *sarray != ctx->text.s.type; sarray++); |
2178 | |
2179 | if (*sarray == XawselectNull) |
2180 | newType = *(ctx->text.sarray); |
2181 | else { |
2182 | newType = *(sarray + 1); |
2183 | if (newType == XawselectNull) |
2184 | newType = *(ctx->text.sarray); |
2185 | } |
2186 | } |
2187 | else /* single-click event */ |
2188 | newType = *(ctx->text.sarray); |
2189 | |
2190 | ctx->text.lasttime = time; |
2191 | } |
2192 | switch (newType) { |
2193 | case XawselectPosition: |
2194 | newLeft = newRight = pos; |
2195 | break; |
2196 | case XawselectChar: |
2197 | newLeft = pos; |
2198 | newRight = SrcScanXawTextSourceScan(src, pos, XawstPositions, XawsdRight, 1, FALSE0); |
2199 | break; |
2200 | case XawselectWord: |
2201 | case XawselectParagraph: |
2202 | { |
2203 | XawTextScanType stype; |
2204 | |
2205 | if (newType == XawselectWord) |
2206 | stype = XawstWhiteSpace; |
2207 | else |
2208 | stype = XawstParagraph; |
2209 | |
2210 | /* |
2211 | * Somewhat complicated, but basically I treat the space between |
2212 | * two objects as another object. The object that I am currently |
2213 | * in then becomes the end of the selection. |
2214 | * |
2215 | * Chris Peterson - 4/19/90. |
2216 | */ |
2217 | |
2218 | newRight = SrcScanXawTextSourceScan(ctx->text.source, pos, stype, XawsdRight, 1, FALSE0); |
2219 | newRight =SrcScanXawTextSourceScan(ctx->text.source, newRight,stype,XawsdLeft,1, FALSE0); |
2220 | |
2221 | if (pos != newRight) |
2222 | newLeft = SrcScanXawTextSourceScan(ctx->text.source, pos, stype, XawsdLeft, 1, FALSE0); |
2223 | else |
2224 | newLeft = pos; |
2225 | |
2226 | newLeft =SrcScanXawTextSourceScan(ctx->text.source, newLeft, stype, XawsdRight,1,FALSE0); |
2227 | |
2228 | if (newLeft > newRight) { |
2229 | XawTextPosition temp = newLeft; |
2230 | newLeft = newRight; |
2231 | newRight = temp; |
2232 | } |
2233 | } |
2234 | break; |
2235 | case XawselectLine: |
2236 | newLeft = SrcScanXawTextSourceScan(src, pos, XawstEOL, XawsdLeft, 1, FALSE0); |
2237 | newRight = SrcScanXawTextSourceScan(src, pos, XawstEOL, XawsdRight, 1, FALSE0); |
2238 | break; |
2239 | case XawselectAll: |
2240 | newLeft = SrcScanXawTextSourceScan(src, pos, XawstAll, XawsdLeft, 1, FALSE0); |
2241 | newRight = SrcScanXawTextSourceScan(src, pos, XawstAll, XawsdRight, 1, FALSE0); |
2242 | break; |
2243 | default: |
2244 | XtAppWarning(XtWidgetToApplicationContext((Widget) ctx), |
2245 | "Text Widget: empty selection array."); |
2246 | return; |
2247 | } |
2248 | |
2249 | if ( (newLeft != ctx->text.s.left) || (newRight != ctx->text.s.right) |
2250 | || (newType != ctx->text.s.type)) { |
2251 | ModifySelection(ctx, newLeft, newRight); |
2252 | if (pos - ctx->text.s.left < ctx->text.s.right - pos) |
2253 | ctx->text.insertPos = newLeft; |
2254 | else |
2255 | ctx->text.insertPos = newRight; |
2256 | ctx->text.s.type = newType; |
2257 | } |
2258 | if (!motion) { /* setup so we can freely mix select extend calls*/ |
2259 | ctx->text.origSel.type = ctx->text.s.type; |
2260 | ctx->text.origSel.left = ctx->text.s.left; |
2261 | ctx->text.origSel.right = ctx->text.s.right; |
2262 | |
2263 | if (pos >= ctx->text.s.left + ((ctx->text.s.right - ctx->text.s.left) / 2)) |
2264 | ctx->text.extendDir = XawsdRight; |
2265 | else |
2266 | ctx->text.extendDir = XawsdLeft; |
2267 | } |
2268 | } |
2269 | |
2270 | /* |
2271 | * This routine implements extension of the currently selected text in |
2272 | * the "current" mode (i.e. char word, line, etc.). It worries about |
2273 | * extending from either end of the selection and handles the case when you |
2274 | * cross through the "center" of the current selection (e.g. switch which |
2275 | * end you are extending!). |
2276 | */ |
2277 | |
2278 | static void |
2279 | ExtendSelection (TextWidget ctx, XawTextPosition pos, Boolean motion) |
2280 | { |
2281 | XawTextScanDirection dir; |
2282 | |
2283 | if (!motion) { /* setup for extending selection */ |
2284 | if (ctx->text.s.left == ctx->text.s.right) /* no current selection. */ |
2285 | ctx->text.s.left = ctx->text.s.right = ctx->text.insertPos; |
2286 | else { |
2287 | ctx->text.origSel.left = ctx->text.s.left; |
2288 | ctx->text.origSel.right = ctx->text.s.right; |
2289 | } |
2290 | |
2291 | ctx->text.origSel.type = ctx->text.s.type; |
2292 | |
2293 | if (pos >= ctx->text.s.left + ((ctx->text.s.right - ctx->text.s.left) / 2)) |
2294 | ctx->text.extendDir = XawsdRight; |
2295 | else |
2296 | ctx->text.extendDir = XawsdLeft; |
2297 | } |
2298 | else /* check for change in extend direction */ |
2299 | if ((ctx->text.extendDir == XawsdRight && pos <= ctx->text.origSel.left) || |
2300 | (ctx->text.extendDir == XawsdLeft && pos >= ctx->text.origSel.right)) { |
2301 | ctx->text.extendDir = (ctx->text.extendDir == XawsdRight) ? |
2302 | XawsdLeft : XawsdRight; |
2303 | ModifySelection(ctx, ctx->text.origSel.left, ctx->text.origSel.right); |
2304 | } |
2305 | |
2306 | dir = ctx->text.extendDir; |
2307 | switch (ctx->text.s.type) { |
2308 | case XawselectWord: |
2309 | case XawselectParagraph: |
2310 | { |
2311 | XawTextPosition left_pos, right_pos; |
2312 | XawTextScanType stype; |
2313 | |
2314 | if (ctx->text.s.type == XawselectWord) |
2315 | stype = XawstWhiteSpace; |
2316 | else |
2317 | stype = XawstParagraph; |
2318 | |
2319 | /* |
2320 | * Somewhat complicated, but basically I treat the space between |
2321 | * two objects as another object. The object that I am currently |
2322 | * in then becomes the end of the selection. |
2323 | * |
2324 | * Chris Peterson - 4/19/90. |
2325 | */ |
2326 | |
2327 | right_pos = SrcScanXawTextSourceScan(ctx->text.source, pos, stype, XawsdRight, 1, FALSE0); |
2328 | right_pos =SrcScanXawTextSourceScan(ctx->text.source, right_pos,stype,XawsdLeft,1, FALSE0); |
2329 | |
2330 | if (pos != right_pos) |
2331 | left_pos = SrcScanXawTextSourceScan(ctx->text.source, pos, stype, XawsdLeft, 1, FALSE0); |
2332 | else |
2333 | left_pos = pos; |
2334 | |
2335 | left_pos =SrcScanXawTextSourceScan(ctx->text.source, left_pos, stype, XawsdRight,1,FALSE0); |
2336 | |
2337 | if (dir == XawsdLeft) |
2338 | pos = Min(left_pos, right_pos)(((left_pos) < (right_pos)) ? (left_pos) : (right_pos)); |
2339 | else /* dir == XawsdRight */ |
2340 | pos = Max(left_pos, right_pos)(((left_pos) > (right_pos)) ? (left_pos) : (right_pos)); |
2341 | } |
2342 | break; |
2343 | case XawselectLine: |
2344 | pos = SrcScanXawTextSourceScan(ctx->text.source, pos, XawstEOL, dir, 1, dir == XawsdRight); |
2345 | break; |
2346 | case XawselectAll: |
2347 | pos = ctx->text.insertPos; |
2348 | case XawselectPosition: /* fall through. */ |
2349 | default: |
2350 | break; |
2351 | } |
2352 | |
2353 | if (dir == XawsdRight) |
2354 | ModifySelection(ctx, ctx->text.s.left, pos); |
2355 | else |
2356 | ModifySelection(ctx, pos, ctx->text.s.right); |
2357 | |
2358 | ctx->text.insertPos = pos; |
2359 | } |
2360 | |
2361 | /* |
2362 | * Clear the window to background color. |
2363 | */ |
2364 | |
2365 | static void |
2366 | ClearWindow (Widget w) |
2367 | { |
2368 | TextWidget ctx = (TextWidget) w; |
2369 | int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; |
2370 | |
2371 | if (XtIsRealized(w)(XtWindowOfObject(w) != 0L)) |
2372 | { |
2373 | SinkClearToBGXawTextSinkClearToBackground(ctx->text.sink, |
2374 | (Position) s, (Position) s, |
2375 | w->core.width - 2 * s, w->core.height - 2 * s); |
2376 | /* note to self: _ShadowSurroundedBox() hack might be needed here */ |
2377 | } |
2378 | } |
2379 | |
2380 | /* Function Name: _XawTextClearAndCenterDisplay |
2381 | * Description: Redraws the display with the cursor in insert point |
2382 | * centered vertically. |
2383 | * Arguments: ctx - the text widget. |
2384 | * Returns: none. |
2385 | */ |
2386 | |
2387 | void |
2388 | _XawTextClearAndCenterDisplay(TextWidget ctx) |
2389 | { |
2390 | int insert_line = LineForPosition(ctx, ctx->text.insertPos); |
2391 | int scroll_by = insert_line - ctx->text.lt.lines/2; |
2392 | |
2393 | _XawTextVScroll(ctx, scroll_by); |
2394 | DisplayTextWindow( (Widget) ctx); |
2395 | } |
2396 | |
2397 | /* |
2398 | * Internal redisplay entire window. |
2399 | * Legal to call only if widget is realized. |
2400 | */ |
2401 | |
2402 | static void |
2403 | DisplayTextWindow (Widget w) |
2404 | { |
2405 | TextWidget ctx = (TextWidget) w; |
2406 | ClearWindow(w); |
2407 | _XawTextBuildLineTable(ctx, ctx->text.lt.top, FALSE0); |
2408 | _XawTextNeedsUpdating(ctx, zeroPosition((XawTextPosition) 0), ctx->text.lastPos); |
2409 | _XawTextSetScrollBars(ctx); |
2410 | } |
2411 | |
2412 | /* |
2413 | * This routine checks to see if the window should be resized (grown or |
2414 | * shrunk) when text to be painted overflows to the right or |
2415 | * the bottom of the window. It is used by the keyboard input routine. |
2416 | */ |
2417 | |
2418 | void |
2419 | _XawTextCheckResize(TextWidget ctx) |
2420 | { |
2421 | Widget w = (Widget) ctx; |
2422 | int line = 0, old_height; |
2423 | XtWidgetGeometry rbox, return_geom; |
2424 | |
2425 | if ( (ctx->text.resize == XawtextResizeWidth) || |
2426 | (ctx->text.resize == XawtextResizeBoth) ) { |
2427 | XawTextLineTableEntry *lt; |
2428 | rbox.width = 0; |
2429 | for (lt = ctx->text.lt.info; |
2430 | IsValidLine(ctx, line)( ((line) == 0) || ((ctx)->text.lt.info[(line)].position != 0) ) && (line < ctx->text.lt.lines); |
2431 | line++, lt++) { |
2432 | if ((int)(lt->textWidth + ctx->text.margin.left) > (int)rbox.width) |
2433 | rbox.width = lt->textWidth + ctx->text.margin.left; |
2434 | } |
2435 | |
2436 | rbox.width += ctx->text.margin.right; |
2437 | if (rbox.width > ctx->core.width) { /* Only get wider. */ |
2438 | rbox.request_mode = CWWidth(1<<2); |
2439 | if (XtMakeGeometryRequest(w, &rbox, &return_geom) == XtGeometryAlmost) |
2440 | (void) XtMakeGeometryRequest(w, &return_geom, (XtWidgetGeometry*) NULL((void*)0)); |
2441 | } |
2442 | } |
2443 | |
2444 | if ( !((ctx->text.resize == XawtextResizeHeight) || |
2445 | (ctx->text.resize == XawtextResizeBoth)) ) |
2446 | return; |
2447 | |
2448 | if (IsPositionVisible(ctx, ctx->text.lastPos)(ctx->text.lastPos >= ctx->text.lt.info[0].position && ctx->text.lastPos < ctx->text.lt.info[ctx->text. lt.lines].position)) |
2449 | line = LineForPosition(ctx, ctx->text.lastPos); |
2450 | else |
2451 | line = ctx->text.lt.lines; |
2452 | |
2453 | if ( (line + 1) == ctx->text.lt.lines ) return; |
2454 | |
2455 | old_height = ctx->core.height; |
2456 | rbox.request_mode = CWHeight(1<<3); |
2457 | rbox.height = XawTextSinkMaxHeight(ctx->text.sink, line + 1) + VMargins(ctx)( (ctx)->text.margin.top + (ctx)->text.margin.bottom ); |
2458 | |
2459 | if ((int)rbox.height < old_height) return; /* It will only get taller. */ |
2460 | |
2461 | if (XtMakeGeometryRequest(w, &rbox, &return_geom) == XtGeometryAlmost) |
2462 | if (XtMakeGeometryRequest(w, &return_geom, (XtWidgetGeometry*)NULL((void*)0)) != XtGeometryYes) |
2463 | return; |
2464 | |
2465 | _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE1); |
2466 | } |
2467 | |
2468 | /* |
2469 | * Converts (params, num_params) to a list of atoms & caches the |
2470 | * list in the TextWidget instance. |
2471 | */ |
2472 | |
2473 | Atom* |
2474 | _XawTextSelectionList(TextWidget ctx, String *list, Cardinal nelems) |
2475 | { |
2476 | Atom * sel = ctx->text.s.selections; |
2477 | Display *dpy = XtDisplay((Widget) ctx)((((Widget) ctx)->core.screen)->display); |
2478 | int n; |
2479 | |
2480 | if (nelems > ctx->text.s.array_size) { |
2481 | sel = (Atom *) XtRealloc((char *) sel, sizeof(Atom) * nelems); |
2482 | ctx->text.s.array_size = nelems; |
2483 | ctx->text.s.selections = sel; |
2484 | } |
2485 | for (n=nelems; --n >= 0; sel++, list++) |
2486 | *sel = XInternAtom(dpy, *list, False0); |
2487 | |
2488 | ctx->text.s.atom_count = nelems; |
2489 | return ctx->text.s.selections; |
2490 | } |
2491 | |
2492 | /* Function Name: SetSelection |
2493 | * Description: Sets the current selection. |
2494 | * Arguments: ctx - the text widget. |
2495 | * defaultSel - the default selection. |
2496 | * l, r - the left and right ends of the selection. |
2497 | * list, nelems - the selection list (as strings). |
2498 | * Returns: none. |
2499 | * |
2500 | * NOTE: if (ctx->text.s.left >= ctx->text.s.right) then the selection |
2501 | * is unset. |
2502 | */ |
2503 | |
2504 | void |
2505 | _XawTextSetSelection(TextWidget ctx, XawTextPosition l, XawTextPosition r, |
2506 | String *list, Cardinal nelems) |
2507 | { |
2508 | if (nelems == 1 && !strcmp (list[0], "none")) |
2509 | return; |
2510 | if (nelems == 0) { |
2511 | String defaultSel = "PRIMARY"; |
2512 | list = &defaultSel; |
2513 | nelems = 1; |
2514 | } |
2515 | _SetSelection(ctx, l, r, _XawTextSelectionList(ctx, list, nelems), nelems); |
2516 | } |
2517 | |
2518 | |
2519 | /* Function Name: ModifySelection |
2520 | * Description: Modifies the current selection. |
2521 | * Arguments: ctx - the text widget. |
2522 | * left, right - the left and right ends of the selection. |
2523 | * Returns: none. |
2524 | * |
2525 | * NOTE: if (ctx->text.s.left >= ctx->text.s.right) then the selection |
2526 | * is unset. |
2527 | */ |
2528 | |
2529 | static void |
2530 | ModifySelection(TextWidget ctx, XawTextPosition left, XawTextPosition right) |
2531 | { |
2532 | if (left == right) |
2533 | ctx->text.insertPos = left; |
2534 | _SetSelection( ctx, left, right, (Atom*) NULL((void*)0), ZERO((Cardinal)0) ); |
2535 | } |
2536 | |
2537 | /* |
2538 | * This routine is used to perform various selection functions. The goal is |
2539 | * to be able to specify all the more popular forms of draw-through and |
2540 | * multi-click selection user interfaces from the outside. |
2541 | */ |
2542 | |
2543 | void |
2544 | _XawTextAlterSelection (TextWidget ctx, XawTextSelectionMode mode, |
2545 | XawTextSelectionAction action, String *params, Cardinal *num_params) |
2546 | { |
2547 | XawTextPosition position; |
2548 | Boolean flag; |
2549 | |
2550 | /* |
2551 | * This flag is used by TextPop.c:DoReplace() to determine if the selection |
2552 | * is okay to use, or if it has been modified. |
2553 | */ |
2554 | |
2555 | if (ctx->text.search != NULL((void*)0)) |
2556 | ctx->text.search->selection_changed = TRUE1; |
2557 | |
2558 | position = PositionForXY (ctx, (int) ctx->text.ev_x, (int) ctx->text.ev_y); |
2559 | |
2560 | flag = (action != XawactionStart); |
2561 | if (mode == XawsmTextSelect) |
2562 | DoSelection (ctx, position, ctx->text.time, flag); |
2563 | else /* mode == XawsmTextExtend */ |
2564 | ExtendSelection (ctx, position, flag); |
2565 | |
2566 | if (action == XawactionEnd) |
2567 | _XawTextSetSelection(ctx, ctx->text.s.left, ctx->text.s.right, |
2568 | params, *num_params); |
2569 | } |
2570 | |
2571 | /* Function Name: RectanglesOverlap |
2572 | * Description: Returns TRUE if two rectangles overlap. |
2573 | * Arguments: rect1, rect2 - the two rectangles to check. |
2574 | * Returns: TRUE iff these rectangles overlap. |
2575 | */ |
2576 | |
2577 | static Boolean |
2578 | RectanglesOverlap(XRectangle *rect1, XRectangle *rect2) |
2579 | { |
2580 | return ( (rect1->x < rect2->x + (short) rect2->width) && |
2581 | (rect2->x < rect1->x + (short) rect1->width) && |
2582 | (rect1->y < rect2->y + (short) rect2->height) && |
2583 | (rect2->y < rect1->y + (short) rect1->height) ); |
2584 | } |
2585 | |
2586 | /* Function Name: UpdateTextInRectangle. |
2587 | * Description: Updates the text in a rectangle. |
2588 | * Arguments: ctx - the text widget. |
2589 | * rect - the rectangle to update. |
2590 | * Returns: none. |
2591 | */ |
2592 | |
2593 | static void |
2594 | UpdateTextInRectangle(TextWidget ctx, XRectangle * rect) |
2595 | { |
2596 | XawTextLineTableEntry *info = ctx->text.lt.info; |
2597 | int line, x = rect->x, y = rect->y; |
2598 | int right = rect->width + x, bottom = rect->height + y; |
2599 | |
2600 | for (line = 0;( (line < ctx->text.lt.lines) && |
2601 | IsValidLine(ctx, line)( ((line) == 0) || ((ctx)->text.lt.info[(line)].position != 0) ) && (info->y < bottom)); line++, info++) |
2602 | if ( (info + 1)->y >= y ) |
2603 | UpdateTextInLine(ctx, line, x, right); |
2604 | } |
2605 | |
2606 | /* |
2607 | * This routine processes all "expose region" XEvents. In general, its job |
2608 | * is to the best job at minimal re-paint of the text, displayed in the |
2609 | * window, that it can. |
2610 | */ |
2611 | |
2612 | /* ARGSUSED */ |
2613 | static void |
2614 | ProcessExposeRegion(Widget w, XEvent *event, Region region) |
2615 | { |
2616 | TextWidget ctx = (TextWidget) w; |
2617 | XRectangle expose, cursor; |
2618 | Boolean need_to_draw; |
2619 | |
2620 | if (event->type == Expose12) { |
2621 | expose.x = event->xexpose.x; |
2622 | expose.y = event->xexpose.y; |
2623 | expose.width = event->xexpose.width; |
2624 | expose.height = event->xexpose.height; |
2625 | } |
2626 | else if (event->type == GraphicsExpose13) { |
2627 | expose.x = event->xgraphicsexpose.x; |
2628 | expose.y = event->xgraphicsexpose.y; |
2629 | expose.width = event->xgraphicsexpose.width; |
2630 | expose.height = event->xgraphicsexpose.height; |
2631 | } |
2632 | else { /* No Expose */ |
2633 | PopCopyQueue(ctx); |
2634 | return; /* no more processing necessary. */ |
2635 | } |
2636 | |
2637 | need_to_draw = TranslateExposeRegion(ctx, &expose); |
2638 | if ((event->type == GraphicsExpose13) && (event->xgraphicsexpose.count == 0)) |
2639 | PopCopyQueue(ctx); |
2640 | |
2641 | if (!need_to_draw) |
2642 | return; /* don't draw if we don't need to. */ |
2643 | |
2644 | _XawTextPrepareToUpdate(ctx); |
2645 | UpdateTextInRectangle(ctx, &expose); |
2646 | XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); |
2647 | if (RectanglesOverlap(&cursor, &expose)) { |
2648 | SinkClearToBGXawTextSinkClearToBackground(ctx->text.sink, (Position) cursor.x, (Position) cursor.y, |
2649 | (Dimension) cursor.width, (Dimension) cursor.height); |
2650 | UpdateTextInRectangle(ctx, &cursor); |
2651 | } |
2652 | _XawTextExecuteUpdate(ctx); |
2653 | |
2654 | _ShadowSurroundedBox((Widget)ctx, (ThreeDWidget)ctx->text.threeD, |
2655 | 0, 0, ctx->core.width, ctx->core.height, |
2656 | ((ThreeDWidget)ctx->text.threeD)->threeD.relief, False0); |
2657 | } |
2658 | |
2659 | /* |
2660 | * This routine does all setup required to syncronize batched screen updates |
2661 | */ |
2662 | |
2663 | void |
2664 | _XawTextPrepareToUpdate(TextWidget ctx) |
2665 | { |
2666 | if (ctx->text.old_insert < 0) { |
2667 | InsertCursor((Widget)ctx, XawisOff); |
2668 | ctx->text.numranges = 0; |
2669 | ctx->text.showposition = FALSE0; |
2670 | ctx->text.old_insert = ctx->text.insertPos; |
2671 | } |
2672 | } |
2673 | |
2674 | /* |
2675 | * This is a private utility routine used by _XawTextExecuteUpdate. It |
2676 | * processes all the outstanding update requests and merges update |
2677 | * ranges where possible. |
2678 | */ |
2679 | |
2680 | static |
2681 | void FlushUpdate(TextWidget ctx) |
2682 | { |
2683 | int i, w; |
2684 | XawTextPosition updateFrom, updateTo; |
2685 | if (!XtIsRealized((Widget)ctx)(XtWindowOfObject((Widget)ctx) != 0L)) { |
2686 | ctx->text.numranges = 0; |
2687 | return; |
2688 | } |
2689 | while (ctx->text.numranges > 0) { |
2690 | updateFrom = ctx->text.updateFrom[0]; |
2691 | w = 0; |
2692 | for (i = 1 ; i < ctx->text.numranges ; i++) { |
2693 | if (ctx->text.updateFrom[i] < updateFrom) { |
2694 | updateFrom = ctx->text.updateFrom[i]; |
2695 | w = i; |
2696 | } |
2697 | } |
2698 | updateTo = ctx->text.updateTo[w]; |
2699 | ctx->text.numranges--; |
2700 | ctx->text.updateFrom[w] = ctx->text.updateFrom[ctx->text.numranges]; |
2701 | ctx->text.updateTo[w] = ctx->text.updateTo[ctx->text.numranges]; |
2702 | for (i = ctx->text.numranges - 1 ; i >= 0 ; i--) { |
2703 | while (ctx->text.updateFrom[i] <= updateTo && i < ctx->text.numranges) { |
2704 | updateTo = ctx->text.updateTo[i]; |
2705 | ctx->text.numranges--; |
2706 | ctx->text.updateFrom[i] = ctx->text.updateFrom[ctx->text.numranges]; |
2707 | ctx->text.updateTo[i] = ctx->text.updateTo[ctx->text.numranges]; |
2708 | } |
2709 | } |
2710 | DisplayText((Widget)ctx, updateFrom, updateTo); |
2711 | } |
2712 | } |
2713 | |
2714 | /* |
2715 | * This is a private utility routine used by _XawTextExecuteUpdate. This |
2716 | * routine worries about edits causing new data or the insertion point becoming |
2717 | * invisible (off the screen, or under the horiz. scrollbar). Currently |
2718 | * it always makes it visible by scrolling. It probably needs |
2719 | * generalization to allow more options. |
2720 | */ |
2721 | |
2722 | void |
2723 | _XawTextShowPosition(TextWidget ctx) |
2724 | { |
2725 | int x, y, lines, number; |
2726 | Boolean no_scroll; |
2727 | XawTextPosition max_pos, top, first; |
2728 | |
2729 | if ( (!XtIsRealized((Widget)ctx)(XtWindowOfObject((Widget)ctx) != 0L)) || (ctx->text.lt.lines <= 0) ) |
2730 | return; |
2731 | |
2732 | /* |
2733 | * Find out the bottom the visable window, and make sure that the |
2734 | * cursor does not go past the end of this space. |
2735 | * |
2736 | * This makes sure that the cursor does not go past the end of the |
2737 | * visable window. |
2738 | */ |
2739 | |
2740 | x = ctx->core.width; |
2741 | y = ctx->core.height - ctx->text.margin.bottom; |
2742 | if (ctx->text.hbar != NULL((void*)0)) |
2743 | y -= ctx->text.hbar->core.height + 2 * ctx->text.hbar->core.border_width; |
2744 | |
2745 | max_pos = PositionForXY (ctx, x, y); |
2746 | lines = LineForPosition(ctx, max_pos) + 1; /* number of visable lines. */ |
2747 | |
2748 | if ( (ctx->text.insertPos >= ctx->text.lt.top) && |
2749 | (ctx->text.insertPos < max_pos)) |
2750 | return; |
2751 | |
2752 | first = ctx->text.lt.top; |
2753 | no_scroll = FALSE0; |
2754 | |
2755 | if (ctx->text.insertPos < first) { /* We need to scroll down. */ |
2756 | top = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos, |
2757 | XawstEOL, XawsdLeft, 1, FALSE0); |
2758 | |
2759 | /* count the number of lines we have to scroll */ |
2760 | |
2761 | number = 0; |
2762 | while (first > top) { |
2763 | first = SrcScanXawTextSourceScan(ctx->text.source, first, |
2764 | XawstEOL, XawsdLeft, 1, TRUE1); |
2765 | |
2766 | if ( - number > lines ) |
2767 | break; |
2768 | |
2769 | number--; |
2770 | } |
2771 | |
2772 | if (first <= top) { /* If we found the proper number |
2773 | of lines. */ |
2774 | |
2775 | /* Back up to just before the last CR. */ |
2776 | |
2777 | first = SrcScanXawTextSourceScan(ctx->text.source, first, |
2778 | XawstPositions, XawsdRight, 1, TRUE1); |
2779 | |
2780 | /* Check to make sure the cursor is visable. */ |
2781 | |
2782 | if (first <= top) |
2783 | number++; |
2784 | |
2785 | lines = number; |
2786 | } |
2787 | else |
2788 | no_scroll = TRUE1; |
2789 | } |
2790 | else { /* We need to Scroll up */ |
2791 | top = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos, |
2792 | XawstEOL, XawsdLeft, lines, FALSE0); |
2793 | |
2794 | if (top < max_pos) |
2795 | lines = LineForPosition(ctx, top); |
2796 | else |
2797 | no_scroll = TRUE1; |
2798 | } |
2799 | |
2800 | if (no_scroll) { |
2801 | _XawTextBuildLineTable(ctx, top, FALSE0); |
2802 | DisplayTextWindow((Widget)ctx); |
2803 | } |
2804 | else |
2805 | _XawTextVScroll(ctx, lines); |
2806 | |
2807 | _XawTextSetScrollBars(ctx); |
2808 | } |
2809 | |
2810 | /* |
2811 | * This routine causes all batched screen updates to be performed |
2812 | */ |
2813 | |
2814 | void |
2815 | _XawTextExecuteUpdate(TextWidget ctx) |
2816 | { |
2817 | if ( ctx->text.update_disabled || (ctx->text.old_insert < 0) ) |
2818 | return; |
2819 | |
2820 | if((ctx->text.old_insert != ctx->text.insertPos) || (ctx->text.showposition)) |
2821 | _XawTextShowPosition(ctx); |
2822 | FlushUpdate(ctx); |
2823 | InsertCursor((Widget)ctx, XawisOn); |
2824 | ctx->text.old_insert = -1; |
2825 | } |
2826 | |
2827 | |
2828 | static void |
2829 | TextDestroy(Widget w) |
2830 | { |
2831 | TextWidget ctx = (TextWidget)w; |
2832 | |
2833 | DestroyHScrollBar(ctx); |
2834 | DestroyVScrollBar(ctx); |
2835 | |
2836 | XtFree((char *)ctx->text.s.selections); |
2837 | XtFree((char *)ctx->text.lt.info); |
2838 | XtFree((char *)ctx->text.search); |
2839 | XtFree((char *)ctx->text.updateFrom); |
2840 | XtFree((char *)ctx->text.updateTo); |
2841 | } |
2842 | |
2843 | /* |
2844 | * by the time we are managed (and get this far) we had better |
2845 | * have both a source and a sink |
2846 | */ |
2847 | |
2848 | static void |
2849 | Resize(Widget w) |
2850 | { |
2851 | TextWidget ctx = (TextWidget) w; |
2852 | |
2853 | PositionVScrollBar(ctx); |
2854 | PositionHScrollBar(ctx); |
2855 | |
2856 | _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE1); |
2857 | _XawTextSetScrollBars(ctx); |
2858 | } |
2859 | |
2860 | /* |
2861 | * This routine allow the application program to Set attributes. |
2862 | */ |
2863 | |
2864 | /*ARGSUSED*/ |
2865 | static Boolean |
2866 | SetValues(Widget current, Widget request, Widget new, ArgList args, Cardinal *num_args) |
2867 | { |
2868 | TextWidget oldtw = (TextWidget) current; |
2869 | TextWidget newtw = (TextWidget) new; |
2870 | Boolean redisplay = FALSE0; |
2871 | Boolean display_caret = newtw->text.display_caret; |
2872 | |
2873 | |
2874 | newtw->text.display_caret = oldtw->text.display_caret; |
2875 | _XawTextPrepareToUpdate(newtw); |
2876 | newtw->text.display_caret = display_caret; |
2877 | |
2878 | if (oldtw->text.r_margin.left != newtw->text.r_margin.left) { |
2879 | newtw->text.margin.left = newtw->text.r_margin.left; |
2880 | if (newtw->text.vbar != NULL((void*)0)) |
2881 | newtw->text.margin.left += newtw->text.vbar->core.width + |
2882 | newtw->text.vbar->core.border_width; |
2883 | redisplay = TRUE1; |
2884 | } |
2885 | |
2886 | if (oldtw->text.scroll_vert != newtw->text.scroll_vert) { |
2887 | if (newtw->text.scroll_vert == XawtextScrollNever) |
2888 | DestroyVScrollBar(newtw); |
2889 | else if (newtw->text.scroll_vert == XawtextScrollAlways) |
2890 | CreateVScrollBar(newtw); |
2891 | redisplay = TRUE1; |
2892 | } |
2893 | |
2894 | if (oldtw->text.r_margin.bottom != newtw->text.r_margin.bottom) { |
2895 | newtw->text.margin.bottom = newtw->text.r_margin.bottom; |
2896 | if (newtw->text.hbar != NULL((void*)0)) |
2897 | newtw->text.margin.bottom += newtw->text.hbar->core.height + |
2898 | newtw->text.hbar->core.border_width; |
2899 | redisplay = TRUE1; |
2900 | } |
2901 | |
2902 | if (oldtw->text.scroll_horiz != newtw->text.scroll_horiz) { |
2903 | if (newtw->text.scroll_horiz == XawtextScrollNever) |
2904 | DestroyHScrollBar(newtw); |
2905 | else if (newtw->text.scroll_horiz == XawtextScrollAlways) |
2906 | CreateHScrollBar(newtw); |
2907 | redisplay = TRUE1; |
2908 | } |
2909 | |
2910 | if ( oldtw->text.source != newtw->text.source ) |
2911 | XawTextSetSource( (Widget) newtw, newtw->text.source, newtw->text.lt.top); |
2912 | |
2913 | newtw->text.redisplay_needed = False0; |
2914 | XtSetValues( (Widget)newtw->text.source, args, *num_args ); |
2915 | XtSetValues( (Widget)newtw->text.sink, args, *num_args ); |
2916 | |
2917 | if ( oldtw->text.wrap != newtw->text.wrap || |
2918 | oldtw->text.lt.top != newtw->text.lt.top || |
2919 | oldtw->text.r_margin.right != newtw->text.r_margin.right || |
2920 | oldtw->text.r_margin.top != newtw->text.r_margin.top || |
2921 | oldtw->text.sink != newtw->text.sink || |
2922 | newtw->text.redisplay_needed ) |
2923 | { |
2924 | _XawTextBuildLineTable(newtw, newtw->text.lt.top, TRUE1); |
2925 | redisplay = TRUE1; |
2926 | } |
2927 | |
2928 | if (oldtw->text.insertPos != newtw->text.insertPos) { |
2929 | newtw->text.showposition = TRUE1; |
2930 | redisplay = TRUE1; |
2931 | } |
2932 | |
2933 | _XawTextExecuteUpdate(newtw); |
2934 | if (redisplay) |
2935 | _XawTextSetScrollBars(newtw); |
2936 | |
2937 | return redisplay; |
2938 | } |
2939 | |
2940 | /* invoked by the Simple widget's SetValues */ |
2941 | static Boolean |
2942 | ChangeSensitive(Widget w) |
2943 | { |
2944 | Arg args[1]; |
2945 | TextWidget tw = (TextWidget) w; |
2946 | |
2947 | (*(&simpleClassRec)->simple_class.change_sensitive)(w); |
2948 | |
2949 | XtSetArg(args[0], XtNancestorSensitive,((void)( (args[0]).name = (((char*)&XtStrings[34])), (args [0]).value = (XtArgVal)((tw->core.ancestor_sensitive && tw->core.sensitive)) )) |
2950 | (tw->core.ancestor_sensitive && tw->core.sensitive))((void)( (args[0]).name = (((char*)&XtStrings[34])), (args [0]).value = (XtArgVal)((tw->core.ancestor_sensitive && tw->core.sensitive)) )); |
2951 | if (tw->text.vbar) |
2952 | XtSetValues(tw->text.vbar, args, ONE((Cardinal)1)); |
2953 | if (tw->text.hbar) |
2954 | XtSetValues(tw->text.hbar, args, ONE((Cardinal)1)); |
2955 | return False0; |
2956 | } |
2957 | |
2958 | /* Function Name: GetValuesHook |
2959 | * Description: This is a get values hook routine that gets the |
2960 | * values in the text source and sink. |
2961 | * Arguments: w - the Text Widget. |
2962 | * args - the argument list. |
2963 | * num_args - the number of args. |
2964 | * Returns: none. |
2965 | */ |
2966 | |
2967 | static void |
2968 | GetValuesHook(Widget w, ArgList args, Cardinal * num_args) |
2969 | { |
2970 | XtGetValues( ((TextWidget) w)->text.source, args, *num_args ); |
2971 | XtGetValues( ((TextWidget) w)->text.sink, args, *num_args ); |
2972 | } |
2973 | |
2974 | /* Function Name: FindGoodPosition |
2975 | * Description: Returns a valid position given any postition |
2976 | * Arguments: pos - any position. |
2977 | * Returns: a position between (0 and lastPos); |
2978 | */ |
2979 | |
2980 | static XawTextPosition |
2981 | FindGoodPosition(TextWidget ctx, XawTextPosition pos) |
2982 | { |
2983 | if (pos < 0) return(0); |
2984 | return ( ((pos > ctx->text.lastPos) ? ctx->text.lastPos : pos) ); |
2985 | } |
2986 | |
2987 | /************************************************************ |
2988 | * |
2989 | * Routines for handling the copy area expose queue. |
2990 | * |
2991 | ************************************************************/ |
2992 | |
2993 | /* Function Name: PushCopyQueue |
2994 | * Description: Pushes a value onto the copy queue. |
2995 | * Arguments: ctx - the text widget. |
2996 | * h, v - amount of offset in the horiz and vert directions. |
2997 | * Returns: none |
2998 | */ |
2999 | |
3000 | static void |
3001 | PushCopyQueue(TextWidget ctx, int h, int v) |
3002 | { |
3003 | struct text_move * offsets = XtNew(struct text_move)((struct text_move *) XtMalloc((unsigned) sizeof(struct text_move ))); |
3004 | |
3005 | offsets->h = h; |
3006 | offsets->v = v; |
3007 | offsets->next = NULL((void*)0); |
3008 | |
3009 | if (ctx->text.copy_area_offsets == NULL((void*)0)) |
3010 | ctx->text.copy_area_offsets = offsets; |
3011 | else { |
3012 | struct text_move * end = ctx->text.copy_area_offsets; |
3013 | for ( ; end->next != NULL((void*)0); end = end->next) {} |
3014 | end->next = offsets; |
3015 | } |
3016 | } |
3017 | |
3018 | /* Function Name: PopCopyQueue |
3019 | * Description: Pops the top value off of the copy queue. |
3020 | * Arguments: ctx - the text widget. |
3021 | * Returns: none. |
3022 | */ |
3023 | |
3024 | static void |
3025 | PopCopyQueue(TextWidget ctx) |
3026 | { |
3027 | struct text_move * offsets = ctx->text.copy_area_offsets; |
3028 | |
3029 | if (offsets == NULL((void*)0)) |
3030 | (void) printf( "Xaw Text widget %s: empty copy queue\n", |
3031 | XtName( (Widget) ctx ) ); |
3032 | else { |
3033 | ctx->text.copy_area_offsets = offsets->next; |
3034 | XtFree((char *) offsets); /* free what you allocate. */ |
3035 | } |
3036 | } |
3037 | |
3038 | /* Function Name: TranslateExposeRegion |
3039 | * Description: Translates the expose that came into |
3040 | * the cordinates that now exist in the Text widget. |
3041 | * Arguments: ctx - the text widget. |
3042 | * expose - a Rectangle, who's region currently |
3043 | * contains the expose event location. |
3044 | * this region will be returned containing |
3045 | * the new rectangle. |
3046 | * Returns: True if there is drawing that needs to be done. |
3047 | */ |
3048 | |
3049 | static Boolean |
3050 | TranslateExposeRegion(TextWidget ctx, XRectangle *expose) |
3051 | { |
3052 | struct text_move * offsets = ctx->text.copy_area_offsets; |
3053 | int value; |
3054 | int x, y, width, height; |
3055 | |
3056 | /* |
3057 | * Skip over the first one, this has already been taken into account. |
3058 | */ |
3059 | |
3060 | if (!offsets || !(offsets = offsets->next)) |
3061 | return(TRUE1); |
3062 | |
3063 | x = expose->x; |
3064 | y = expose->y; |
3065 | width = expose->width; |
3066 | height = expose->height; |
3067 | |
3068 | while (offsets) { |
3069 | x += offsets->h; |
3070 | y += offsets->v; |
3071 | offsets = offsets->next; |
3072 | } |
3073 | |
3074 | /* |
3075 | * remove that area of the region that is now outside the window. |
3076 | */ |
3077 | |
3078 | if (y < 0) { |
3079 | height += y; |
3080 | y = 0; |
3081 | } |
3082 | |
3083 | value = y + height - ctx->core.height; |
3084 | if (value > 0) |
3085 | height -= value; |
3086 | |
3087 | if (height <= 0) |
3088 | return(FALSE0); /* no need to draw outside the window. */ |
3089 | |
3090 | /* |
3091 | * and now in the horiz direction... |
3092 | */ |
3093 | |
3094 | if (x < 0) { |
3095 | width += x; |
3096 | x = 0; |
3097 | } |
3098 | |
3099 | value = x + width - ctx->core.width; |
3100 | if (value > 0) |
3101 | width -= value; |
3102 | |
3103 | if (width <= 0) |
3104 | return(FALSE0); /* no need to draw outside the window. */ |
3105 | |
3106 | expose->x = x; |
3107 | expose->y = y; |
3108 | expose->width = width; |
3109 | expose->height = height; |
3110 | return(TRUE1); |
3111 | } |
3112 | |
3113 | /* Li wrote this so the IM can find a given text position's screen position. */ |
3114 | |
3115 | void |
3116 | _XawTextPosToXY( |
3117 | Widget w, |
3118 | XawTextPosition pos, |
3119 | Position* x, |
3120 | Position* y ) |
3121 | { |
3122 | int line; |
3123 | LineAndXYForPosition( (TextWidget)w, pos, &line, x, y ); |
3124 | } |
3125 | |
3126 | /******************************************************************* |
3127 | The following routines provide procedural interfaces to Text window state |
3128 | setting and getting. They need to be redone so than the args code can use |
3129 | them. I suggest we create a complete set that takes the context as an |
3130 | argument and then have the public version lookup the context and call the |
3131 | internal one. The major value of this set is that they have actual application |
3132 | clients and therefore the functionality provided is required for any future |
3133 | version of Text. |
3134 | ********************************************************************/ |
3135 | |
3136 | void |
3137 | XawTextDisplay (Widget w) |
3138 | { |
3139 | if (!XtIsRealized(w)(XtWindowOfObject(w) != 0L)) return; |
3140 | |
3141 | _XawTextPrepareToUpdate( (TextWidget) w); |
3142 | DisplayTextWindow(w); |
3143 | _XawTextExecuteUpdate( (TextWidget) w); |
3144 | } |
3145 | |
3146 | void |
3147 | XawTextSetSelectionArray(Widget w, XawTextSelectType *sarray) |
3148 | { |
3149 | ((TextWidget)w)->text.sarray = sarray; |
3150 | } |
3151 | |
3152 | void |
3153 | XawTextGetSelectionPos(Widget w, XawTextPosition *left, XawTextPosition *right) |
3154 | { |
3155 | *left = ((TextWidget) w)->text.s.left; |
3156 | *right = ((TextWidget) w)->text.s.right; |
3157 | } |
3158 | |
3159 | |
3160 | void |
3161 | XawTextSetSource(Widget w, Widget source, XawTextPosition startPos) |
3162 | { |
3163 | TextWidget ctx = (TextWidget) w; |
3164 | |
3165 | ctx->text.source = source; |
3166 | ctx->text.lt.top = startPos; |
3167 | ctx->text.s.left = ctx->text.s.right = 0; |
3168 | ctx->text.insertPos = startPos; |
3169 | ctx->text.lastPos = GETLASTPOSXawTextSourceScan(ctx->text.source, 0, XawstAll, XawsdRight , 1, 1); |
3170 | |
3171 | _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE1); |
3172 | XawTextDisplay(w); |
3173 | } |
3174 | |
3175 | /* |
3176 | * This public routine deletes the text from startPos to endPos in a source and |
3177 | * then inserts, at startPos, the text that was passed. As a side effect it |
3178 | * "invalidates" that portion of the displayed text (if any), so that things |
3179 | * will be repainted properly. |
3180 | */ |
3181 | |
3182 | int |
3183 | XawTextReplace(Widget w, XawTextPosition startPos, XawTextPosition endPos, |
3184 | XawTextBlock *text) |
3185 | { |
3186 | TextWidget ctx = (TextWidget) w; |
3187 | int result; |
3188 | |
3189 | _XawTextPrepareToUpdate(ctx); |
3190 | endPos = FindGoodPosition(ctx, endPos); |
3191 | startPos = FindGoodPosition(ctx, startPos); |
3192 | if ((result = _XawTextReplace(ctx, startPos, endPos, text)) == XawEditDone0) { |
3193 | int delta = text->length - (endPos - startPos); |
3194 | if (ctx->text.insertPos >= (endPos + delta)) { |
3195 | XawTextScanDirection sd = (delta < 0) ? XawsdLeft : XawsdRight; |
3196 | ctx->text.insertPos = SrcScanXawTextSourceScan(ctx->text.source, ctx->text.insertPos, |
3197 | XawstPositions, sd, abs(delta), TRUE1); |
3198 | } |
3199 | } |
3200 | |
3201 | _XawTextCheckResize(ctx); |
3202 | _XawTextExecuteUpdate(ctx); |
3203 | _XawTextSetScrollBars(ctx); |
3204 | |
3205 | return result; |
3206 | } |
3207 | |
3208 | XawTextPosition |
3209 | XawTextTopPosition(Widget w) |
3210 | { |
3211 | return( ((TextWidget) w)->text.lt.top ); |
3212 | } |
3213 | |
3214 | void |
3215 | XawTextSetInsertionPoint(Widget w, XawTextPosition position) |
3216 | { |
3217 | TextWidget ctx = (TextWidget) w; |
3218 | |
3219 | _XawTextPrepareToUpdate(ctx); |
3220 | ctx->text.insertPos = FindGoodPosition(ctx, position); |
3221 | ctx->text.showposition = TRUE1; |
3222 | |
3223 | _XawTextExecuteUpdate(ctx); |
3224 | } |
3225 | |
3226 | XawTextPosition |
3227 | XawTextGetInsertionPoint(Widget w) |
3228 | { |
3229 | return( ((TextWidget) w)->text.insertPos); |
3230 | } |
3231 | |
3232 | /* |
3233 | * NOTE: Must walk the selection list in opposite order from LoseSelection. |
3234 | */ |
3235 | |
3236 | void |
3237 | XawTextUnsetSelection(Widget w) |
3238 | { |
3239 | TextWidget ctx = (TextWidget)w; |
3240 | |
3241 | while (ctx->text.s.atom_count != 0) { |
3242 | Atom sel = ctx->text.s.selections[ctx->text.s.atom_count - 1]; |
3243 | if ( sel != (Atom) 0 ) { |
3244 | /* |
3245 | * As selections are lost the atom_count will decrement. |
3246 | */ |
3247 | if (GetCutBufferNumber(sel) == NOT_A_CUT_BUFFER-1) |
3248 | XtDisownSelection(w, sel, ctx->text.time); |
3249 | LoseSelection(w, &sel); /* In case this is a cut buffer, or |
3250 | XtDisownSelection failed to call us. */ |
3251 | } |
3252 | } |
3253 | } |
3254 | |
3255 | void |
3256 | XawTextSetSelection (Widget w, XawTextPosition left, XawTextPosition right) |
3257 | { |
3258 | TextWidget ctx = (TextWidget) w; |
3259 | |
3260 | _XawTextPrepareToUpdate(ctx); |
3261 | _XawTextSetSelection(ctx, FindGoodPosition(ctx, left), |
3262 | FindGoodPosition(ctx, right), (String*)NULL((void*)0), ZERO((Cardinal)0)); |
3263 | _XawTextExecuteUpdate(ctx); |
3264 | } |
3265 | |
3266 | void |
3267 | XawTextInvalidate(Widget w, XawTextPosition from, XawTextPosition to) |
3268 | { |
3269 | TextWidget ctx = (TextWidget) w; |
3270 | |
3271 | from = FindGoodPosition(ctx, from); |
3272 | to = FindGoodPosition(ctx, to); |
3273 | ctx->text.lastPos = GETLASTPOSXawTextSourceScan(ctx->text.source, 0, XawstAll, XawsdRight , 1, 1); |
3274 | _XawTextPrepareToUpdate(ctx); |
3275 | _XawTextNeedsUpdating(ctx, from, to); |
3276 | _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE1); |
3277 | _XawTextExecuteUpdate(ctx); |
3278 | } |
3279 | |
3280 | /*ARGSUSED*/ |
3281 | void |
3282 | XawTextDisableRedisplay(Widget w) |
3283 | { |
3284 | ((TextWidget) w)->text.update_disabled = True1; |
3285 | _XawTextPrepareToUpdate( (TextWidget) w); |
3286 | } |
3287 | |
3288 | void |
3289 | XawTextEnableRedisplay(Widget w) |
3290 | { |
3291 | TextWidget ctx = (TextWidget)w; |
3292 | XawTextPosition lastPos; |
3293 | |
3294 | if (!ctx->text.update_disabled) return; |
3295 | |
3296 | ctx->text.update_disabled = False0; |
3297 | lastPos = ctx->text.lastPos = GETLASTPOSXawTextSourceScan(ctx->text.source, 0, XawstAll, XawsdRight , 1, 1); |
3298 | ctx->text.lt.top = FindGoodPosition(ctx, ctx->text.lt.top); |
3299 | ctx->text.insertPos = FindGoodPosition(ctx, ctx->text.insertPos); |
3300 | if ( (ctx->text.s.left > lastPos) || (ctx->text.s.right > lastPos) ) |
3301 | ctx->text.s.left = ctx->text.s.right = 0; |
3302 | |
3303 | _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE1); |
3304 | if (XtIsRealized(w)(XtWindowOfObject(w) != 0L)) |
3305 | DisplayTextWindow(w); |
3306 | _XawTextExecuteUpdate(ctx); |
3307 | } |
3308 | |
3309 | Widget |
3310 | XawTextGetSource(Widget w) |
3311 | { |
3312 | return ((TextWidget)w)->text.source; |
3313 | } |
3314 | |
3315 | Widget |
3316 | XawTextGetSink(Widget w) |
3317 | { |
3318 | return (((TextWidget)w)->text.sink); |
3319 | } |
3320 | |
3321 | void |
3322 | XawTextDisplayCaret (Widget w, |
3323 | #if NeedWidePrototypes1 |
3324 | /* Boolean */ int display_caret) |
3325 | #else |
3326 | Boolean display_caret) |
3327 | #endif |
3328 | { |
3329 | TextWidget ctx = (TextWidget) w; |
3330 | |
3331 | if (ctx->text.display_caret == display_caret) return; |
3332 | |
3333 | if (XtIsRealized(w)(XtWindowOfObject(w) != 0L)) { |
3334 | _XawTextPrepareToUpdate(ctx); |
3335 | ctx->text.display_caret = display_caret; |
3336 | _XawTextExecuteUpdate(ctx); |
3337 | } |
3338 | else |
3339 | ctx->text.display_caret = display_caret; |
3340 | } |
3341 | |
3342 | /* Function Name: XawTextSearch(w, dir, text). |
3343 | * Description: searches for the given text block. |
3344 | * Arguments: w - The text widget. |
3345 | * dir - The direction to search. |
3346 | * text - The text block containing info about the string |
3347 | * to search for. |
3348 | * Returns: The position of the text found, or XawTextSearchError on |
3349 | * an error. |
3350 | */ |
3351 | |
3352 | XawTextPosition |
3353 | XawTextSearch(Widget w, |
3354 | #if NeedWidePrototypes1 |
3355 | /* XawTextScanDirection */ int dir, |
3356 | #else |
3357 | XawTextScanDirection dir, |
3358 | #endif |
3359 | XawTextBlock *text) |
3360 | { |
3361 | TextWidget ctx = (TextWidget) w; |
3362 | |
3363 | return(SrcSearchXawTextSourceSearch(ctx->text.source, ctx->text.insertPos, dir, text)); |
3364 | } |
3365 | |
3366 | TextClassRec textClassRec = { |
3367 | { /* core fields */ |
3368 | /* superclass */ (WidgetClass) &simpleClassRec, |
3369 | /* class_name */ "Text", |
3370 | /* widget_size */ sizeof(TextRec), |
3371 | /* class_initialize */ ClassInitialize, |
3372 | /* class_part_init */ NULL((void*)0), |
3373 | /* class_inited */ FALSE0, |
3374 | /* initialize */ Initialize, |
3375 | /* initialize_hook */ NULL((void*)0), |
3376 | /* realize */ Realize, |
3377 | /* actions */ _XawTextActionsTable, |
3378 | /* num_actions */ 0, /* Set in ClassInitialize. */ |
3379 | /* resources */ resources, |
3380 | /* num_ resource */ XtNumber(resources)((Cardinal) (sizeof(resources) / sizeof(resources[0]))), |
3381 | /* xrm_class */ NULLQUARK((XrmQuark) 0), |
3382 | /* compress_motion */ TRUE1, |
3383 | /* compress_exposure*/ XtExposeGraphicsExpose0x10 | XtExposeNoExpose0x40, |
3384 | /* compress_enterleave*/ TRUE1, |
3385 | /* visible_interest */ FALSE0, |
3386 | /* destroy */ TextDestroy, |
3387 | /* resize */ Resize, |
3388 | /* expose */ ProcessExposeRegion, |
3389 | /* set_values */ SetValues, |
3390 | /* set_values_hook */ NULL((void*)0), |
3391 | /* set_values_almost*/ XtInheritSetValuesAlmost((XtAlmostProc) _XtInherit), |
3392 | /* get_values_hook */ GetValuesHook, |
3393 | /* accept_focus */ NULL((void*)0), |
3394 | /* version */ XtVersion(11 * 1000 + 6), |
3395 | /* callback_private */ NULL((void*)0), |
3396 | /* tm_table */ NULL((void*)0), /* set in ClassInitialize */ |
3397 | /* query_geometry */ XtInheritQueryGeometry((XtGeometryHandler) _XtInherit), |
3398 | /* display_accelerator*/ XtInheritDisplayAccelerator((XtStringProc) _XtInherit), |
3399 | /* extension */ NULL((void*)0) |
3400 | }, |
3401 | { /* Simple fields */ |
3402 | /* change_sensitive */ ChangeSensitive |
3403 | }, |
3404 | { /* text fields */ |
3405 | /* empty */ 0 |
3406 | } |
3407 | }; |
3408 | |
3409 | WidgetClass textWidgetClass = (WidgetClass)&textClassRec; |