1 /*
2 PLIB - A Suite of Portable Game Libraries
3 Copyright (C) 1998,2002 Steve Baker
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 For further information visit http://plib.sourceforge.net
20
21 $Id: puAuxLargeInput.cxx 2068 2006-03-20 15:17:35Z fayjf $
22 */
23
24
25 #include "puAuxLocal.h"
26
UL_RTTI_DEF2(puaLargeInput,puInputBase,puGroup)27 UL_RTTI_DEF2(puaLargeInput,puInputBase,puGroup)
28
29
30 // Callbacks from the internal widgets
31
32 static void puaLargeInputHandleRightSlider ( puObject *slider )
33 {
34 float val = ((puaScrollBar *)slider)->getMaxValue () - slider->getFloatValue () ;
35
36 puaLargeInput* text = (puaLargeInput*) slider->getUserData () ;
37 //int lines_in_window = text->getLinesInWindow () ;
38 int num_lines = text->getNumLines () ;
39
40 if ( num_lines > 0 )
41 text->setTopLineInWindow ( int ( val + 0.5f ) ) ;
42 }
43
44 // Private function from the widget itself
45
normalizeCursors(void)46 void puaLargeInput::normalizeCursors ( void )
47 {
48 puInputBase::normalizeCursors () ;
49
50 // Set the top line in the window so that the last line is at the bottom of the window
51
52 if ( top_line_in_window > num_lines - lines_in_window + 2 )
53 top_line_in_window = num_lines - lines_in_window + 2 ;
54
55 if ( top_line_in_window < 0 ) top_line_in_window = 0 ;
56 }
57
removeSelectRegion(void)58 void puaLargeInput::removeSelectRegion ( void )
59 {
60 puInputBase::removeSelectRegion () ;
61
62 wrapText () ;
63 }
64
65
66 // Public functions from the widget itself
67
puaLargeInput(int x,int y,int w,int h,int arrows,int sl_width,int wrap_text)68 puaLargeInput::puaLargeInput ( int x, int y, int w, int h, int arrows, int sl_width, int wrap_text ) :
69 puInputBase (), puGroup ( x, y )
70 {
71 setColour ( PUCOL_MISC, 0.1f, 0.1f, 1.0f ) ; // Colour of the 'I' bar cursor
72
73 // Set the variables
74
75 type |= PUCLASS_LARGEINPUT ;
76 num_lines = 1 ;
77 slider_width = sl_width ;
78 lines_in_window = ( h - (bottom_slider?slider_width:0) ) /
79 ( getLegendFont().getStringHeight() + getLegendFont().getStringDescender() + 1 ) ;
80 top_line_in_window = 0 ;
81 max_width = 0 ;
82
83 widget = this ;
84
85 // Set up the widgets
86
87 frame = new puFrame ( 0, 0, w, h );
88
89 if ( wrap_text )
90 bottom_slider = (puSlider *)NULL ;
91 else
92 {
93 bottom_slider = new puSlider ( 0, 0, w - slider_width, FALSE, slider_width ) ,
94 bottom_slider->setValue ( 0.0f ) ; // All the way to the left
95 // bottom_slider->setDelta(0.1f); // Commented out CBModes and Deltas for these sliders to increase response time and to ensure the sliders react properly even when first selected - JCJ 13 Jun 2002
96 bottom_slider->setSliderFraction (1.0f) ;
97 // bottom_slider->setCBMode( PUSLIDER_DELTA );
98 }
99
100 right_slider = new puaScrollBar ( w - slider_width, (bottom_slider?slider_width:0),
101 h - (bottom_slider?slider_width:0), arrows, TRUE, slider_width ) ,
102 right_slider->setValue ( 1.0f ) ; // All the way to the top
103 // right_slider->setDelta(0.1f);
104 right_slider->setSliderFraction (1.0f) ;
105 right_slider->setStepSize ( 1.0f ) ;
106 // right_slider->setCBMode( PUSLIDER_DELTA );
107 right_slider->setUserData ( this ) ;
108 right_slider->setCallback ( puaLargeInputHandleRightSlider ) ;
109
110 setValue ( "\n" ) ;
111
112 close () ;
113 reveal () ;
114 }
115
setSize(int w,int h)116 void puaLargeInput::setSize ( int w, int h )
117 {
118 // Resize the frame:
119 frame->setSize ( w, h ) ;
120
121 // Resize and reposition the sliders
122 if ( bottom_slider )
123 bottom_slider->setSize ( w - slider_width, slider_width ) ;
124 else // No bottom slider, rewrap the text
125 wrapText () ;
126
127 right_slider->setPosition ( w-slider_width, (bottom_slider?slider_width:0) ) ;
128 right_slider->setSize ( slider_width, h-(bottom_slider?slider_width:0) ) ;
129
130 lines_in_window = ( h - (bottom_slider?slider_width:0) ) /
131 ( getLegendFont().getStringHeight() + getLegendFont().getStringDescender() + 1 ) ;
132
133 int line_size = legendFont.getStringHeight () + // Height of a line
134 legendFont.getStringDescender() ; // of text, in pixels
135 int box_height = ( abox.max[1] - abox.min[1] - slider_width ) / line_size ;
136 int right_slider_max = num_lines - lines_in_window + 1 ;
137 if ( right_slider_max < 1 ) right_slider_max = 1 ;
138
139 right_slider->setSliderFraction ( float(box_height) / float(right_slider_max) ) ;
140 right_slider->setMaxValue ( float(right_slider_max) ) ;
141 }
142
setSelectRegion(int s,int e)143 void puaLargeInput::setSelectRegion ( int s, int e )
144 {
145 select_start_position = s ;
146 select_end_position = e ;
147 char *lin_ptr = ( bottom_slider ? getStringValue () : getDisplayedText () ) ;
148 char *text_start = lin_ptr ;
149
150 if ( num_lines > lines_in_window )
151 {
152 int select_start_line = 0 ;
153 while ( lin_ptr && ( lin_ptr <= text_start + select_start_position ) ) // Count the lines
154 {
155 select_start_line++ ;
156 lin_ptr = strchr ( lin_ptr+1, '\n' ) ;
157 }
158
159 int select_end_line = select_start_line ;
160 while ( lin_ptr && ( lin_ptr <= text_start + select_end_position ) ) // Count the lines
161 {
162 select_end_line++ ;
163 lin_ptr = strchr ( lin_ptr+1, '\n' ) ;
164 }
165
166 if ( select_end_line > top_line_in_window + lines_in_window )
167 top_line_in_window = select_end_line - lines_in_window - 1 ;
168
169 if ( select_start_line < top_line_in_window )
170 top_line_in_window = select_start_line - 1 ;
171
172 if ( top_line_in_window < 0 ) top_line_in_window = 0 ;
173
174 right_slider->setValue ( num_lines - lines_in_window - top_line_in_window ) ;
175 }
176 }
177
selectEntireLine(void)178 void puaLargeInput::selectEntireLine ( void )
179 {
180 char *temp_text = ( bottom_slider ? getStringValue () : getDisplayedText () ) ;
181
182 if ( select_start_position < 0 )
183 select_start_position = 0 ;
184
185 if ( ( *(temp_text + select_start_position + 1) != '\n' ) &&
186 ( *(temp_text + select_start_position) != '\0' ) )
187 select_start_position ++ ;
188
189 while ( ( select_start_position > 0 ) && ( *(temp_text + select_start_position) != '\n' ) )
190 select_start_position -- ;
191
192 if ( select_start_position > 0 )
193 select_start_position++ ;
194
195 select_end_position = int ( strchr ( temp_text + select_end_position, '\n' ) + 1 - temp_text) ;
196 if ( select_end_position <= 1 ) select_end_position = strlen ( temp_text ) ;
197 //else select_end_position = int ( select_end_position - temp_text ) ;/** Needs real fixing **/
198
199 puPostRefresh () ;
200 }
201
addNewLine(const char * l)202 void puaLargeInput::addNewLine ( const char *l )
203 {
204 char *text = getStringValue () ;
205 if ( cursor_position > 0 ) // If not at start of line, go to start of next line
206 cursor_position = int (strchr ( text + cursor_position - 1, '\n' ) - text + 1) ;
207
208 select_end_position = select_start_position = cursor_position ;
209 addText ( l ) ;
210 }
211
addText(const char * l)212 void puaLargeInput::addText ( const char *l )
213 {
214 char *text = getStringValue () ;
215
216 if ( l == NULL ) return ;
217
218 int l_len = strlen ( l ) ;
219 int text_len = strlen ( text ) ;
220 int length = l_len + text_len /* Length of the final string */
221 + select_start_position - select_end_position + 2 ;
222 if ( *(l+l_len-1) == '\n' ) length -- ; // Decrement "length" for each final
223 if ( text[select_end_position] == '\n' ) length -- ; // carriage return already there
224
225 char *temp_text = new char [ length ] ;
226
227 memcpy ( temp_text, text, select_start_position ) ;
228 memcpy ( temp_text + select_start_position, l, l_len + 1 ) ; /* Plus one to get the final '\0' */
229 int temp_text_len = select_start_position + l_len ;
230
231 if ( ( *(l+l_len-1) == '\n' ) && ( text[select_end_position] == '\n' ) )
232 {
233 temp_text[temp_text_len-1] = '\0' ; /* Erase the duplicate carriage return */
234 temp_text_len -- ;
235 }
236 else if ( ( *(l+l_len-1) != '\n' ) && ( text[select_end_position] != '\n' ) )
237 {
238 strcpy ( temp_text + temp_text_len, "\n" ) ; /* Add a carriage return */
239 temp_text_len ++ ;
240 }
241
242 memcpy ( temp_text + temp_text_len, text + select_end_position, text_len - select_end_position + 1 ) ;
243 int temp_select_start = select_start_position ;
244 setValue ( temp_text ) ;
245 delete [] temp_text ;
246 setSelectRegion ( temp_select_start,
247 temp_select_start + strlen(l) ) ;
248 setCursor ( select_end_position ) ;
249 }
250
appendText(const char * l)251 void puaLargeInput::appendText ( const char *l )
252 {
253 if ( !l ) return ;
254
255 int str_val_len = strlen ( getStringValue () ) ;
256 int l_len = strlen ( l ) ;
257 if ( str_val_len == 1 ) str_val_len = 0 ; /* Don't want null line at the beginning */
258 int length = str_val_len + l_len + 2 ;
259 if ( *(l+l_len-1) == '\n' ) length -- ; /* Already have a trailing carriage return, decrement the length */
260
261 char *temp_text = new char [ length ] ;
262 int temp_text_len ;
263
264 if ( str_val_len > 0 ) /* More than just the empty carriage return */
265 {
266 memcpy ( temp_text, getStringValue (), str_val_len ) ;
267 temp_text_len = str_val_len ;
268 }
269 else
270 temp_text_len = 0 ;
271
272 memcpy ( temp_text + temp_text_len, l, l_len + 1 ) ; /* Plus one to get the final '\0' */
273 temp_text_len += l_len ;
274 if ( *(l+l_len-1) != '\n' )
275 {
276 strcpy ( temp_text + temp_text_len, "\n" ) ;
277 temp_text_len ++ ;
278 }
279
280 setValue ( temp_text ) ;
281 setSelectRegion ( str_val_len, temp_text_len ) ;
282 setCursor ( str_val_len ) ;
283 delete [] temp_text ;
284 }
285
removeText(int start,int end)286 void puaLargeInput::removeText ( int start, int end )
287 {
288 int str_val_len = strlen ( getStringValue () ) ;
289 char *temp_text = new char [ str_val_len + start - end + 1 ] ;
290 memcpy ( temp_text, getStringValue (), start ) ;
291 memcpy ( temp_text + start, getStringValue ()+end, str_val_len - end + 1 ) ; /* Plus one to get the final '\0' */
292 setValue ( temp_text ) ;
293 setCursor ( start ) ;
294 setSelectRegion ( start, start ) ;
295 delete [] temp_text ;
296 }
297
setValue(const char * s)298 void puaLargeInput::setValue ( const char *s )
299 {
300 if ( bottom_slider ) bottom_slider->setSliderFraction ( 0.0f ) ;
301 right_slider->setSliderFraction ( 0.0f ) ;
302
303 if ( s == NULL )
304 {
305 puValue::setValue ( "\n" ) ;
306 num_lines = 0 ;
307 cursor_position = select_start_position = select_end_position = 0 ;
308 return ;
309 }
310
311 int s_len = strlen ( s ) ;
312 int length = s_len + 2 ;
313 if ( ( s_len > 0 ) && ( *(s+s_len-1) == '\n' ) )
314 length -- ; /* Already have a trailing carriage return, don't need to add one */
315
316 char *text = new char [ length ] ;
317 memcpy ( text, s, s_len + 1 ) ; /* Plus one to get the final '\0' */
318 if ( ( s [ 0 ] == '\0' ) || ( *(s+s_len-1) != '\n' ) )
319 strcpy ( text + s_len, "\n" ) ;
320
321 puValue::setValue ( text ) ;
322 delete [] text ;
323
324 // Find the greatest width of a line
325 max_width = 0 ;
326
327 float line_width = 0.0f ; // Width of current line
328 if ( !bottom_slider ) wrapText () ;
329 char *this_char = ( bottom_slider ? getStringValue () : getDisplayedText () ) ; // Pointer to character in text
330
331 num_lines = 0 ;
332
333 while ( *this_char != '\0' )
334 {
335 char *line_end = strchr ( this_char, '\n' ) ;
336 if ( line_end ) // Found an end-of-line
337 {
338 *line_end = '\0' ; // Temporary break in line
339 line_width = legendFont.getFloatStringWidth ( this_char ) ;
340 *line_end = '\n' ; // Reset the carriage return
341
342 if ( max_width < line_width )
343 max_width = line_width ;
344
345 num_lines++ ; // Increment line counter
346
347 this_char = line_end + 1 ;
348 }
349 else // No carriage return. Since a carriage return should be the last character,
350 this_char++ ; // we should not get here.
351 }
352
353 if ( max_width < line_width )
354 max_width = line_width ;
355
356 // Set slider fractions
357
358 int line_size = legendFont.getStringHeight () + // Height of a line
359 legendFont.getStringDescender() ; // of text, in pixels
360
361 int box_width = abox.max[0] - abox.min[0] - slider_width ; // Input box width, in pixels
362 int box_height = ( abox.max[1] - abox.min[1] - slider_width ) / line_size ;
363 // Input box height, in lines
364
365 if ( bottom_slider )
366 bottom_slider->setSliderFraction ( float(box_width) / float(max_width) ) ;
367
368 int right_slider_max = num_lines - lines_in_window + 1 ;
369 if ( right_slider_max < 1 ) right_slider_max = 1 ;
370
371 right_slider->setSliderFraction ( float(box_height) / float(right_slider_max) ) ;
372 right_slider->setMaxValue ( float(right_slider_max) ) ;
373
374 // Normalize the cursors
375 normalizeCursors () ;
376 }
377
378
draw(int dx,int dy)379 void puaLargeInput::draw ( int dx, int dy )
380 {
381 if ( !visible || ( window != puGetWindow () ) ) return ;
382 normalizeCursors () ;
383
384 // 3D Input boxes look nicest if they are always in inverse style.
385
386 abox.draw ( dx, dy, ( (style==PUSTYLE_SMALL_BEVELLED ||
387 style==PUSTYLE_SMALL_SHADED) ) ? -style :
388 (accepting ? -style : style ), colour, FALSE, border_thickness ) ;
389
390 if ( r_cb )
391 r_cb ( this, dx, dy, render_data ) ;
392 else
393 {
394 // Calculate window parameters:
395
396 int xwidget = abox.min[0] + dx ;
397 int ywidget = abox.min[1] + dy ;
398
399 int line_size = legendFont.getStringHeight () + // Height of a line
400 legendFont.getStringDescender() + 1 ; // of text, in pixels
401
402 int xx = int(legendFont.getFloatStringWidth ( " " )) ;
403 int yy = int( abox.max[1] - abox.min[1] - legendFont.getStringHeight () * 1.5f ) ;
404
405 int box_width = abox.max[0] - abox.min[0] - slider_width - xx - xx ; // Input box width, in pixels
406 int box_height = ( abox.max[1] - abox.min[1] - (bottom_slider?slider_width:0) ) / line_size ;
407 // Input box height, in lines
408
409 float bottom_value = bottom_slider ? bottom_slider->getFloatValue () : 0.0f ;
410
411 int beg_pos // Position in window of start of line, in pixels
412 = int(( box_width - max_width ) * bottom_value ) ;
413 //// int end_pos // Position in window of end of line, in pixels
414 //// = beg_pos + max_width - 1 ;
415 if ( top_line_in_window < 0 ) top_line_in_window = 0 ;
416 int end_lin // Position on line count of bottom of window, in lines
417 = top_line_in_window + box_height ;
418
419 /* Removed IF statement to permit highlighting to remain even when widget not active - JCJ 13 Jun 2002 */
420
421 char *val = bottom_slider ? getStringValue () : getDisplayedText () ;
422
423 // Highlight the select area
424
425 if ( select_end_position > 0 &&
426 select_end_position != select_start_position )
427 {
428 // First: find the positions on the window of the selection start and end
429
430 char temp_char = val[ select_start_position ] ;
431 val [ select_start_position ] = '\0' ;
432
433 xx = dx + abox.min[0] + int(legendFont.getFloatStringWidth ( " " )) ;
434 yy = (int)( abox.max[1] - abox.min[1] - legendFont.getStringHeight () * 1.5f
435 + top_line_in_window * line_size ) ; // Offset y-coord for unprinted lines
436
437 char *end_of_line = strchr ( val, '\n' ) ;
438 char *start_of_line = val;
439
440 // Step down the lines until you reach the line with the selection start
441
442 int select_start_line = 0 ;
443
444 while ( end_of_line )
445 {
446 select_start_line++ ;
447 start_of_line = end_of_line + 1 ;
448 yy -= line_size ;
449 end_of_line = strchr ( start_of_line, '\n' ) ;
450 }
451
452 int start_pos = int(legendFont.getFloatStringWidth ( start_of_line )) + xx +
453 beg_pos ; // Start of selection
454
455 val [ select_start_position ] = temp_char ;
456
457 // Now repeat the process for the end of the selection.
458
459 temp_char = val[ select_end_position ] ;
460 val [ select_end_position ] = '\0' ;
461
462 end_of_line = strchr ( start_of_line, '\n' ) ;
463
464 // Step down the lines until you reach the line with the selection end
465
466 int select_end_line = select_start_line ;
467
468 while ( end_of_line )
469 {
470 select_end_line++ ;
471 start_of_line = end_of_line + 1 ;
472 end_of_line = strchr ( start_of_line, '\n' ) ;
473 }
474
475 int end_pos = int(legendFont.getFloatStringWidth ( start_of_line )) + xx +
476 beg_pos ; // End of selection
477
478 val [ select_end_position ] = temp_char ;
479
480 // Now draw the selection area.
481
482 for ( int line_count = select_start_line ; ( ( line_count <= select_end_line ) && ( line_count <= end_lin ) ) ;
483 line_count++ )
484 {
485 if ( line_count >= top_line_in_window )
486 {
487 int x_start, x_end ;
488
489 if ( line_count == select_start_line )
490 x_start = ( start_pos > xx ) ? start_pos : xx ;
491 else
492 x_start = xx ;
493
494 x_start = ( x_start < abox.max[0] + dx ) ? x_start : abox.max[0] + dx ;
495
496 if ( line_count == select_end_line )
497 x_end = ( end_pos < abox.max[0] + dx ) ? end_pos : abox.max[0] + dx ;
498 else
499 x_end = abox.max[0] + dx ;
500
501 x_end = ( x_end > xx ) ? x_end : xx ;
502
503 int top = dy + abox.min[1] + yy + legendFont.getStringHeight () ;
504 int bot = dy + abox.min[1] + yy - legendFont.getStringDescender() ;
505
506 glColor3f ( 1.0f, 1.0f, 0.7f ) ;
507 glRecti ( x_start, bot, x_end, top ) ;
508 }
509
510 yy -= line_size ;
511 if ( line_count == end_lin ) break ;
512 }
513 }
514
515
516 // Draw the text
517
518 {
519 // If greyed out then halve the opacity when drawing the text
520
521 if ( active )
522 glColor4fv ( colour [ PUCOL_LEGEND ] ) ;
523 else
524 glColor4f ( colour [ PUCOL_LEGEND ][0],
525 colour [ PUCOL_LEGEND ][1],
526 colour [ PUCOL_LEGEND ][2],
527 colour [ PUCOL_LEGEND ][3] / 2.0f ) ; // 50% more transparent
528
529 char *val ; // Pointer to the actual text in the box
530 val = bottom_slider ? getStringValue () : getDisplayedText () ;
531
532 if ( val )
533 {
534 char *end_of_line = strchr (val, '\n') ;
535 int line_count = 0;
536
537 xx = int(legendFont.getFloatStringWidth ( " " )) ;
538 yy = int( abox.max[1] - abox.min[1] - legendFont.getStringHeight () * 1.5f ) ;
539
540 while ( end_of_line ) // While there is a carriage return in the string
541 {
542 if ( line_count < top_line_in_window )
543 { // Before the start of the window
544 val = end_of_line + 1 ;
545 end_of_line = strchr (val, '\n') ; // Just go to the next line
546 }
547 else if ( line_count <= end_lin ) // Within the window, draw it
548 {
549 char temp_char = *end_of_line ; // Temporary holder for last char on line
550
551 *end_of_line = '\0' ; // Make end-of-line be an end-of-string
552
553 int start_pos = beg_pos ;
554 int end_pos // Position in window of end of line, in pixels
555 = start_pos + int(legendFont.getFloatStringWidth ( val )) ;
556
557 if ( end_pos > start_pos ) // If we actually have text in the line
558 {
559 char * lastonleft = val ;
560 char * firstonright = end_of_line ;
561 int leftpos = start_pos ;
562 int rightpos = end_pos ;
563 while ( lastonleft < firstonright - 1 )
564 {
565 int chpos = -leftpos * ( firstonright - lastonleft ) / ( rightpos - leftpos ) + 1;
566 if ( chpos >= firstonright - lastonleft ) chpos = firstonright - lastonleft - 1 ;
567 char placeholder = *(lastonleft + chpos) ;
568 *(lastonleft + chpos) = '\0' ;
569 int strwidth = legendFont.getStringWidth ( val ) ;
570 *(lastonleft + chpos) = placeholder ;
571 if ( strwidth + start_pos < 0 ) /* Still to the left of the window */
572 {
573 lastonleft = lastonleft + chpos ;
574 placeholder = *lastonleft ;
575 *lastonleft = '\0' ;
576 leftpos = start_pos + legendFont.getStringWidth ( val ) ;
577 *lastonleft = placeholder ;
578 }
579 else
580 {
581 firstonright = lastonleft + chpos ;
582 placeholder = *firstonright ;
583 *firstonright = '\0' ;
584 rightpos = start_pos + legendFont.getStringWidth ( val ) ;
585 *firstonright = placeholder ;
586 }
587 }
588 if ( leftpos >= 0 )
589 {
590 val = lastonleft ;
591 start_pos = leftpos ;
592 }
593 else
594 {
595 val = firstonright ;
596 start_pos = rightpos ;
597 }
598 }
599
600 while ( end_pos > box_width ) // Step up the line until it is in the window
601 {
602 *end_of_line = temp_char ;
603 end_of_line-- ;
604 temp_char = *end_of_line ;
605 *end_of_line = '\0' ;
606 end_pos = start_pos + legendFont.getStringWidth ( val ) ;
607 }
608
609 if ( val < end_of_line ) // If any text shows in the window,
610 legendFont.drawString ( val, // draw it.
611 dx + abox.min[0] + xx + start_pos,
612 dy + abox.min[1] + yy ) ;
613
614 *end_of_line = temp_char ; // Restore the end-of-line character
615
616 if ( temp_char != '\n' ) // If we had to step up from the end of
617 end_of_line = strchr (val, '\n') ; // the line, go back to the actual end
618
619 yy -= line_size ;
620 val = end_of_line + 1 ;
621 end_of_line = strchr (val, '\n') ; // On to the next line
622 }
623 else if ( line_count > end_lin ) // Have gone beyond window, end process
624 end_of_line = NULL ;
625
626 line_count++ ;
627
628 } // while ( end_of_line )
629 } // if ( val )
630 }
631
632 if ( accepting )
633 {
634 char *val ; // Pointer to the actual text in the box
635 val = bottom_slider ? getStringValue () : getDisplayedText () ;
636
637 // Draw the 'I' bar cursor.
638
639 if ( val && ( cursor_position >= 0 ) )
640 {
641 char temp_char = val[ cursor_position ] ;
642 val [ cursor_position ] = '\0' ;
643
644 xx = int(legendFont.getFloatStringWidth ( " " )) ;
645 yy = int( abox.max[1] - abox.min[1] - legendFont.getStringHeight () * 1.5f )
646 + top_line_in_window * line_size ; // Offset y-coord for unprinted lines
647
648 char *end_of_line = strchr ( val, '\n' ) ;
649 char *start_of_line = val ;
650
651 // Step down the lines until you reach the line with the cursor
652
653 int line_count = 1 ;
654
655 while ( end_of_line )
656 {
657 line_count++ ;
658 start_of_line = end_of_line + 1 ;
659 yy -= line_size ;
660 end_of_line = strchr ( start_of_line, '\n' ) ;
661 }
662
663 if ( ( line_count > top_line_in_window ) && ( line_count <= end_lin ) )
664 {
665 int begpos // Position in window of start of line, in pixels
666 = int( ( box_width - max_width ) * bottom_value ) ;
667 int cpos = int( legendFont.getFloatStringWidth ( start_of_line ) + xx +
668 abox.min[0] + begpos ) ;
669 int top = int( abox.min[1] + yy + legendFont.getStringHeight () ) ;
670 int bot = int( abox.min[1] + yy - legendFont.getStringDescender () ) ;
671 if ( ( cpos > abox.min[0] ) && ( cpos < abox.max[0] ) )
672 {
673 glColor4fv ( colour [ PUCOL_MISC ] ) ;
674 glBegin ( GL_LINES ) ;
675 glVertex2i ( dx + cpos , dy + bot ) ;
676 glVertex2i ( dx + cpos , dy + top ) ;
677 glVertex2i ( dx + cpos - 1, dy + bot ) ;
678 glVertex2i ( dx + cpos - 1, dy + top ) ;
679 glVertex2i ( dx + cpos - 4, dy + bot ) ;
680 glVertex2i ( dx + cpos + 3, dy + bot ) ;
681 glVertex2i ( dx + cpos - 4, dy + top ) ;
682 glVertex2i ( dx + cpos + 3, dy + top ) ;
683 glEnd () ;
684 }
685 }
686
687 val[ cursor_position ] = temp_char ;
688 }
689 }
690
691 // Draw the other widgets in the large input box
692
693 if ( bottom_slider ) bottom_slider->draw ( xwidget, ywidget ) ;
694 right_slider->draw ( xwidget, ywidget ) ;
695 }
696
697 draw_label ( dx, dy ) ;
698 }
699
700
checkHit(int button,int updown,int x,int y)701 int puaLargeInput::checkHit ( int button, int updown, int x, int y )
702 {
703 int xwidget = x - abox.min[0] ;
704 int ywidget = y - abox.min[1] ;
705
706 if ( bottom_slider )
707 {
708 if ( bottom_slider->checkHit ( button, updown, xwidget, ywidget ) ) return TRUE ;
709 }
710
711 if ( right_slider->checkHit ( button, updown, xwidget, ywidget ) ) return TRUE ;
712
713 // If the user has clicked within the bottom slider or to its right, don't activate.
714
715 if ( y < slider_width ) return FALSE ;
716
717 if ( puObject::checkHit ( button, updown, x, y ) )
718 return TRUE ;
719
720 return FALSE ;
721 }
722
723
doHit(int button,int updown,int x,int y)724 void puaLargeInput::doHit ( int button, int updown, int x, int y )
725 {
726 if ( puActiveWidget() && ( this != puActiveWidget() ) )
727 {
728 // Active widget exists and is not this one; call its down callback if it exists
729
730 puActiveWidget()->invokeDownCallback () ;
731 puDeactivateWidget () ;
732 }
733
734 if ( updown != PU_DRAG )
735 puMoveToLast ( this );
736
737 if ( button == active_mouse_button )
738 {
739 // Most GUI's activate a button on button-UP not button-DOWN.
740
741 // Text and window parameters:
742
743 int line_size = legendFont.getStringHeight () + // Height of a line
744 legendFont.getStringDescender() + 1 ; // of text, in pixels
745
746 int box_width = abox.max[0] - abox.min[0] - slider_width ; // Input box width, in pixels
747 // int box_height = ( abox.max[1] - abox.min[1] ) / line_size ;
748 // Input box height, in lines
749
750 float bottom_value = bottom_slider ? bottom_slider->getFloatValue () : 0.0f ;
751
752 int beg_pos // Position in window of start of line, in pixels
753 = int( ( box_width - max_width ) * bottom_value ) ;
754 // int end_pos // Position in window of end of line, in pixels
755 // = (int)( beg_pos + max_width - 1 ) ;
756 if ( top_line_in_window < 0 ) top_line_in_window = 0 ;
757 // int end_lin // Position on line count of bottom of window, in lines
758 // = top_line_in_window + box_height - 1 ;
759
760 // int xx = legendFont.getStringWidth ( " " ) ;
761 int yy = int( abox.max[1] - legendFont.getStringHeight () * 1.5f
762 + top_line_in_window * line_size ) ; // Offset y-coord for unprinted lines
763
764 // Get the line number and position on the line of the mouse
765
766 char *strval = bottom_slider ? getStringValue () : getDisplayedText () ;
767 char *tmpval = ulStrDup ( strval ) ;
768
769 int i = strlen ( tmpval ) ;
770
771 char *end_of_line = strchr ( tmpval, '\n' ) ;
772 char *start_of_line = tmpval;
773
774 // Step down the lines until the y-coordinate is less than the mouse
775
776 int line_count = 0 ;
777
778 while ( ( yy > y ) && end_of_line )
779 {
780 line_count++ ;
781 start_of_line = end_of_line + 1 ;
782 yy -= line_size ;
783 end_of_line = strchr ( start_of_line, '\n' ) ;
784 }
785
786 if ( end_of_line )
787 {
788 *end_of_line = '\0' ;
789
790 i = strlen ( tmpval ) ;
791
792 int length, prev_length = 0 ;
793 while ( x <= (length = legendFont.getStringWidth ( start_of_line )
794 + abox.min[0] + beg_pos) &&
795 i > 0 )
796 {
797 prev_length = length ;
798 tmpval[--i] = '\0' ;
799 }
800
801 if ( ( x - length ) < ( prev_length - x ) )
802 i-- ; // Mouse is closer to previous character than next character
803 }
804
805 // Now process the mouse click itself.
806
807 if ( updown == active_mouse_edge || active_mouse_edge == PU_UP_AND_DOWN )
808 {
809 lowlight () ;
810
811 accepting = TRUE ;
812 cursor_position = i ;
813 normalizeCursors () ;
814 puSetActiveWidget ( this, x, y ) ;
815 invokeCallback () ;
816 }
817 else if ( updown == PU_DOWN )
818 {
819 // We get here if the active edge is not down but the mouse button has
820 // been pressed. Start a selection.
821
822 select_start_position = i ;
823 select_end_position = i ;
824 }
825 else if ( updown == PU_DRAG )
826 {
827 // Drag -- extend the selection.
828
829 if ( (select_end_position - i) > (i - select_start_position) )
830 select_start_position = i ; // Cursor closer to start than to end
831 else
832 select_end_position = i ; // Cursor closer to end than to start
833
834 if (select_start_position > select_end_position)
835 {
836 i = select_end_position ;
837 select_end_position = select_start_position ;
838 select_start_position = i ;
839 }
840 }
841 else
842 highlight () ;
843
844 delete [] tmpval ;
845 }
846 else
847 lowlight () ;
848 }
849
checkKey(int key,int updown)850 int puaLargeInput::checkKey ( int key, int updown )
851 {
852 if ( updown == PU_UP || !isAcceptingInput () || !isActive () ||
853 !isVisible () || ( window != puGetWindow () ) )
854 return FALSE ;
855
856 if ( puActiveWidget() && ( this != puActiveWidget() ) )
857 {
858 // Active widget exists and is not this one; call its down callback if it exists
859
860 puActiveWidget()->invokeDownCallback () ;
861 puDeactivateWidget () ;
862 }
863
864 normalizeCursors () ;
865
866 //char *old_text = getStringValue () ;
867 char *old_text = bottom_slider ? getStringValue () : getDisplayedText () ;
868 int lines_in_window = getLinesInWindow () ; /* Added lines_in_window and num_lines to allow for "END" */
869 int num_lines = getNumLines () ; /* and PGUP/DOWN to work properly - JCJ 20 Jun 2002 */
870 int line_width = 0 ; /* Width of current line (for bottomslider) */
871 int line_width_to_cursor = 0 ; /* Width of current line up to the cursor position */
872 int prev_line_width = 0 ; /* Width of previous line (for left mouse arrow) */
873 int i = 1; /* Happy useful variable */
874 int line_counter = 0 ; /* Happy useful variable #2 */
875 int box_width = abox.max[0] - abox.min[0] - slider_width ; /* Text box width */
876 int tmp_cursor_position = cursor_position ; /* Temporary cursor position for counting without moving the cursor */
877 int bottom_line_in_window = 0; /* # of bottom line in window */
878 int current_line_in_window = 0; /* Current line # in window */
879 char *line_end = 0 ;
880 char* p = new char[ strlen(old_text)+1 ] ;
881 float bottom_value = bottom_slider ? bottom_slider->getFloatValue () : 0.0f ; /* Value of the bottom slider */
882 if ( old_text[1] != '\0' ) /* Ensure that we don't delete something that doesn't exist! - JCJ 22 July 2002 */
883 {
884 /*Count how many characters from the beginning of the line the cursor is*/
885 while ( ( old_text [ cursor_position - i ] != '\n' ) &&
886 ( i < cursor_position ) )
887 i++ ; /* Step back to the beginning of the line */
888 if ( i < cursor_position ) i-- ;
889
890 /*Find the length of the current line*/
891 while ( ( old_text [ tmp_cursor_position ] != '\n' ) &&
892 ( tmp_cursor_position > 0) )
893 tmp_cursor_position-- ;
894
895 strcpy ( p, ( old_text + tmp_cursor_position + 1 ) ) ;
896 if ( bottom_slider )
897 {
898 line_end = strchr ( p, '\n' ) ;
899 if ( line_end ) // Found an end-of-line
900 {
901 *line_end = '\0' ; // Temporary break in line
902 line_width = int(legendFont.getFloatStringWidth ( p )) ;
903 *line_end = '\n' ; // Reset the carriage return
904 }
905 /*Now delete all characters in the string beyond i, and re-find its width*/
906 p [i+1] = '\0' ;
907 line_width_to_cursor = int(legendFont.getFloatStringWidth ( p )) ;
908 }
909
910 /* Now find the length of the previous line */
911 tmp_cursor_position-- ;
912 while ( ( old_text [ tmp_cursor_position ] != '\n' ) &&
913 ( tmp_cursor_position > 0) )
914 tmp_cursor_position-- ;
915
916 strcpy ( p, ( old_text + tmp_cursor_position + 1 ) ) ;
917 if ( bottom_slider )
918 {
919 line_end = strchr ( p, '\n' ) ;
920 if ( line_end ) /*Actually, we KNOW there's a line after this one, but hey, let's be safe, eh? - JCJ 21 Jun 2002 */
921 {
922 *line_end = '\0' ; // Temporary break in line
923 prev_line_width = legendFont.getStringWidth ( p ) ;
924 *line_end = '\n' ; // Reset the carriage return
925 }
926 }
927
928 delete [] p ;
929 p = NULL ;
930 }
931
932 bool done = true ;
933
934 switch ( key )
935 {
936 case PU_KEY_PAGE_UP :
937 while ( old_text [ cursor_position ] != '\0' ) /* Move the cursor to the top of the data */
938 cursor_position-- ;
939 select_start_position = select_end_position = cursor_position ;
940 setTopLineInWindow ( top_line_in_window - lines_in_window + 2 ) ;
941 right_slider->setValue (1.0f - float(top_line_in_window) / num_lines ) ;
942 break;
943 case PU_KEY_PAGE_DOWN :
944 while ( old_text [ cursor_position ] != '\0' ) /* Move the cursor to the end of the data */
945 cursor_position++ ;
946 select_start_position = select_end_position = cursor_position ;
947 setTopLineInWindow ( top_line_in_window + lines_in_window - 2 ) ; /* Plus two for consistency - JCJ 20 Jun 2002 */
948 right_slider->setValue (1.0f - float(top_line_in_window) / num_lines ) ;
949 break;
950 case PU_KEY_INSERT : return FALSE ;
951
952 case PU_KEY_UP :
953 case PU_KEY_DOWN :
954 /* Determine the current line, the line at the top of the window, and the line at the bottom.*/
955 bottom_line_in_window = top_line_in_window + getLinesInWindow() ;
956 while ( line_counter < cursor_position) {
957 if ( old_text [ line_counter ] == '\n' ) current_line_in_window++ ;
958 line_counter++ ;
959 }
960 if ( key == PU_KEY_UP )
961 {
962 // Step backwards to the beginning of the previous line
963 cursor_position -= (i + 2) ;
964 while ( ( old_text [ cursor_position ] != '\n' ) &&
965 ( cursor_position > 0 ) )
966 cursor_position-- ;
967 if ( cursor_position > 0 ) cursor_position++ ;
968
969 // Step down the line "i" spaces or to the end of the line
970 while ( ( old_text [ cursor_position ] != '\n' ) &&
971 ( i > 0 ) )
972 {
973 cursor_position++ ;
974 i-- ;
975 }
976 if (current_line_in_window <= top_line_in_window) {
977 setTopLineInWindow ( top_line_in_window - 1 ); /* Go up - JCJ 21 Jun 2002 */
978 right_slider->setValue (1.0f - float(top_line_in_window) / num_lines ) ;
979 }
980 }
981 else // Down-arrow key
982 {
983 // Skip to beginning of next line
984 while ( old_text [ cursor_position ] != '\n' && old_text [ cursor_position ] != '\0' )
985 cursor_position++ ;
986 cursor_position++ ;
987
988 // Step down the line "i" spaces or to the end of the line
989 // or to the end of the text
990
991 while ( ( old_text [ cursor_position ] != '\n' ) &&
992 ( cursor_position < (int)strlen ( old_text ) ) &&
993 ( i > 0 ) )
994 {
995 cursor_position++ ;
996 i-- ;
997 }
998 if ((current_line_in_window+1) >= bottom_line_in_window) {
999 setTopLineInWindow ( top_line_in_window + 1 ); /* Go down - JCJ 21 Jun 2002 */
1000 right_slider->setValue (1.0f - float(top_line_in_window) / num_lines ) ;
1001 }
1002
1003 }
1004
1005 select_start_position = select_end_position = cursor_position ;
1006 break ;
1007
1008 case 0x1B : // ESC
1009 case '\t' : // TAB -- End of input
1010 rejectInput () ;
1011 normalizeCursors () ;
1012 invokeCallback () ;
1013 puDeactivateWidget () ;
1014 break ;
1015
1016 case PU_KEY_HOME :
1017 while ( ( old_text [ cursor_position-1 ] != '\n' ) &&
1018 ( cursor_position > 0 ) ) /* Move the cursor to the start of the line, but minus one so */
1019 cursor_position-- ; /* it does not find a \n immediately if located at the end. */
1020 select_start_position = select_end_position = cursor_position ; /* Also corrects overshoots. - JCJ 20 Jun 2002 */
1021 if ( bottom_slider ) bottom_slider->setValue ( 0.0f ) ;
1022 break ;
1023 case PU_KEY_END :
1024 if (bottom_slider)
1025 {
1026 bottom_slider->setValue ( ( (line_width - box_width)<0 ) ? 0.0f : float(line_width+10) / max_width);
1027 }
1028 while ( old_text [ cursor_position ] != '\n' ) /* Move the cursor to the end of the line - JCJ 20 Jun 2002 */
1029 cursor_position++ ;
1030 select_start_position = select_end_position = cursor_position ;
1031 break ;
1032
1033 case PU_KEY_LEFT :
1034 case PU_KEY_RIGHT :
1035 if ( key == PU_KEY_LEFT )
1036 {
1037 /* This stops it crashing out sometimes when wrappable text is used.
1038 * Since there is no bottom scrollbar when wrapped text is turned on, the bottom
1039 * slider code could make the application die when the user pressed the left
1040 * cursor key before they began the first line.
1041 * Fix by Simon <sickz6sickz AT hotmail DOT com> */
1042 cursor_position-- ; /* Left key pressed */
1043 if ( bottom_slider )
1044 {
1045 if (old_text [ cursor_position ] == '\n')
1046 bottom_slider->setValue( ( (prev_line_width - box_width)<0 ) ? 0.0f : float(prev_line_width+10) /max_width);
1047 /* If the cursor is going off the left edge of the box, scroll left. */
1048 else if ((bottom_value*max_width) > line_width_to_cursor+5) {
1049 bottom_slider->setValue( ((bottom_value*max_width)-(box_width/2)-5)<0 ? 0.0f :
1050 ((bottom_value*max_width)-(box_width/2)-5)/max_width ) ;
1051 }
1052 }
1053 } else {
1054 cursor_position++ ; /* Right key pressed */
1055 if ( bottom_slider ) {
1056 if (old_text [ cursor_position-1 ] == '\n')
1057 bottom_slider->setValue(0.0f) ;
1058 else if ((bottom_value*max_width)+(box_width) < line_width_to_cursor+5) {
1059 bottom_slider->setValue( ((bottom_value*max_width)+(box_width/2)+5)/max_width ) ;
1060 }
1061 }
1062 }
1063 select_start_position = select_end_position = cursor_position ;
1064 break ;
1065
1066 default :
1067 done = false ;
1068 break ;
1069 }
1070
1071 if ( ! done && ! input_disabled )
1072 {
1073 char *p = NULL ;
1074 int temp_cursor = cursor_position ;
1075
1076 switch ( key )
1077 {
1078 case '\b' : // Backspace
1079 if ( select_start_position != select_end_position )
1080 removeSelectRegion () ;
1081 else if ( cursor_position > 0 )
1082 {
1083 p = new char [ strlen(old_text) ] ;
1084 memcpy ( p, old_text, cursor_position ) ;
1085 --cursor_position ;
1086 strcpy ( p + cursor_position, old_text + cursor_position + 1 ) ;
1087 setValue ( p ) ;
1088 setCursor ( temp_cursor - 1 ) ;
1089 delete [] p ;
1090 }
1091
1092 break ;
1093
1094 case 0x7F : // DEL
1095 if ( select_start_position != select_end_position )
1096 removeSelectRegion () ;
1097 else if (cursor_position != (int)strlen ( old_text ) )
1098 {
1099 p = new char [ strlen(old_text) ] ;
1100 memcpy ( p, old_text, cursor_position ) ;
1101 strcpy ( p + cursor_position, old_text + cursor_position + 1 ) ;
1102 setValue ( p ) ;
1103 setCursor ( temp_cursor ) ;
1104 delete [] p ;
1105 }
1106
1107 break ;
1108
1109 case 0x15 /* ^U */ : getStringValue () [ 0 ] = '\0' ; break ;
1110 case 0x03 /* ^C */ :
1111 case 0x18 /* ^X */ : /* Cut or copy selected text */
1112 if ( select_start_position != select_end_position )
1113 {
1114 extern void puSetPasteBuffer ( const char *ch ) ;
1115 p = getStringValue () ;
1116 char ch = p[select_end_position] ;
1117 p[select_end_position] = '\0' ;
1118 puSetPasteBuffer ( p + select_start_position ) ;
1119 p[select_end_position] = ch ;
1120
1121 if ( key == 0x18 ) /* Cut, remove text from string */
1122 removeSelectRegion () ;
1123 }
1124
1125 break ;
1126
1127 case 0x16 /* ^V */ : /* Paste buffer into text */
1128 {
1129 extern char *puGetPasteBuffer () ;
1130 if ( select_start_position != select_end_position )
1131 removeSelectRegion () ;
1132
1133 if ( puGetPasteBuffer () ) // Make sure something has been cut previously!
1134 {
1135 int str_val_len = strlen ( getStringValue () ) ;
1136 int paste_len = strlen ( puGetPasteBuffer () ) ;
1137 p = new char [ str_val_len + paste_len + 1 ] ;
1138 memcpy ( p, getStringValue (), cursor_position ) ;
1139 memcpy ( p + cursor_position, puGetPasteBuffer (), paste_len ) ;
1140 memcpy ( p + cursor_position + paste_len, getStringValue() + cursor_position, str_val_len - cursor_position + 1 ) ;
1141 temp_cursor += paste_len ;
1142 setValue ( p ) ;
1143 setCursor ( temp_cursor ) ;
1144 delete [] p ;
1145 }
1146 }
1147
1148 break ;
1149
1150 default:
1151 if ( ( key < ' ' || key > 127 ) && ( key != '\n' )
1152 && ( key != '\r' ) ) return FALSE ;
1153
1154 if ( key == '\r' ) key = '\n' ;
1155
1156 if ( valid_data )
1157 {
1158 if ( !strchr ( valid_data, key ) ) return TRUE ;
1159 }
1160
1161 if ( select_start_position != select_end_position ) // remove selected text
1162 {
1163 temp_cursor -= ( select_end_position - select_start_position ) ;
1164 removeSelectRegion () ;
1165 }
1166
1167 p = new char [ strlen(old_text) + 2 ] ;
1168
1169 memcpy ( p, old_text, cursor_position ) ;
1170
1171 p [ cursor_position ] = key ;
1172
1173 strcpy ( p + cursor_position + 1, ( old_text + cursor_position ) ) ;
1174 bottom_line_in_window = top_line_in_window + getLinesInWindow() ;
1175
1176 /* If running off the screen, scroll right. - JCJ 28 Jun 2002 */
1177 if ((bottom_value*max_width)+(box_width) < line_width_to_cursor+5) {
1178 bottom_slider->setValue( ((bottom_value*max_width)+(box_width/2)+5)/max_width ) ;
1179 }
1180
1181 if (key == '\n') {
1182 /* If pressing enter, figure out which line this is. */
1183 while ( line_counter < cursor_position) {
1184 if ( old_text [ line_counter ] == '\n' ) current_line_in_window++ ;
1185 line_counter++ ;
1186 }
1187 /* If hitting enter at the bottom of the screen, scroll down. - JCJ 28 Jun 2002 */
1188 if ( (current_line_in_window+1) >= bottom_line_in_window ) {
1189 setTopLineInWindow ( top_line_in_window + 1 );
1190 right_slider->setValue (1.0f - float(top_line_in_window) / num_lines ) ;
1191 }
1192 }
1193
1194 setValue ( p ) ;
1195 setCursor ( temp_cursor + 1 ) ;
1196 delete [] p ;
1197
1198 break ;
1199 }
1200 }
1201
1202 normalizeCursors () ;
1203 return TRUE ;
1204 }
1205
wrapText(void)1206 void puaLargeInput::wrapText ( void )
1207 {
1208 // Wrap the text in "text" and put it in "displayed_text"
1209
1210 delete [] displayed_text ;
1211 displayed_text = ulStrDup ( getStringValue () ) ;
1212
1213 char *displayed_text_wp = displayed_text,
1214 *space_ptr,
1215 *old_space_ptr ;
1216
1217 /* Somewhat inspired by tuxracer */
1218 while ( *displayed_text_wp != '\0' )
1219 {
1220 old_space_ptr = NULL ;
1221 space_ptr = strchr ( displayed_text_wp, ' ' ) ;
1222
1223 while (1)
1224 {
1225 if ( space_ptr != NULL )
1226 *space_ptr = '\0' ;
1227
1228 if ( legendFont.getStringWidth ( displayed_text_wp ) >
1229 ( ( abox.max[0] - abox.min[0] )
1230 - slider_width
1231 - PUSTR_LGAP
1232 - ( getStyle () == PUSTYLE_BOXED ? getBorderThickness () : 0 )
1233 - PUSTR_RGAP
1234 )
1235 )
1236 break ;
1237
1238 old_space_ptr = space_ptr ;
1239
1240 if ( space_ptr == NULL )
1241 /* Entire string fits in widget */
1242 break ;
1243
1244 // Check for carriage return in the original string
1245 if ( strrchr ( displayed_text_wp, '\n' ) > displayed_text_wp )
1246 displayed_text_wp = strrchr ( displayed_text_wp, '\n' ) + 1 ;
1247
1248 *space_ptr = ' ' ;
1249
1250 space_ptr = strchr ( space_ptr+1, ' ' ) ;
1251 }
1252
1253 if ( old_space_ptr == NULL )
1254 /* Either string is too wide for area, or the entire remaining portion
1255 of string fits in area (space_ptr == NULL). */
1256 {
1257 displayed_text_wp += strlen (displayed_text_wp) ;
1258
1259 if ( space_ptr != NULL )
1260 /* Advance past the NULL since there's more string left */
1261 displayed_text_wp += 1 ;
1262 }
1263 else
1264 {
1265 if ( space_ptr != NULL )
1266 *space_ptr = ' ' ;
1267 *old_space_ptr = '\n' ;
1268
1269 displayed_text_wp = old_space_ptr + 1 ;
1270 }
1271 }
1272 }
1273
1274
1275