1 // High level management of views
2 // Copyright (C) 2004 Core Technologies.
3 
4 // This file is part of e93.
5 //
6 // e93 is free software; you can redistribute it and/or modify
7 // it under the terms of the e93 LICENSE AGREEMENT.
8 //
9 // e93 is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // e93 LICENSE AGREEMENT for more details.
13 //
14 // You should have received a copy of the e93 LICENSE AGREEMENT
15 // along with e93; see the file "LICENSE.TXT".
16 
17 #include	"includes.h"
18 
GetSelectionInView(EDITOR_VIEW * view,SELECTION_UNIVERSE * selection)19 static SELECTION_UNIVERSE *GetSelectionInView(EDITOR_VIEW *view,SELECTION_UNIVERSE *selection)
20 // Work out a selection which is the part of the passed selection which
21 // intersects the visible view.
22 // If there is a problem, clean up, and return NULL
23 {
24 	UINT32
25 		topLine,
26 		numLines;
27 	INT32
28 		leftPixel;
29 	UINT32
30 		numPixels;
31 	CHUNK_HEADER
32 		*chunk;
33 	UINT32
34 		offset,
35 		startPosition,
36 		endPosition;
37 	SELECTION_UNIVERSE
38 		*selectionOut;
39 
40 	if((selectionOut=OpenSelectionUniverse()))					// get selection to work in
41 	{
42 		GetEditorViewTextInfo(view,&topLine,&numLines,&leftPixel,&numPixels);
43 
44 		LineToChunkPosition(view->parentBuffer->textUniverse,topLine,&chunk,&offset,&startPosition);		// get position of top line in this view
45 		LineToChunkPosition(view->parentBuffer->textUniverse,topLine+numLines,&chunk,&offset,&endPosition);	// get position past last line in this view
46 
47 		SetSelectionRange(selectionOut,startPosition,endPosition-startPosition);			// select the entire visible area of the view
48 		AndSelectionUniverse(selection,selectionOut);			// get only the visible part of the current selection
49 	}
50 	return(selectionOut);
51 }
52 
ViewEndSelectionChange(EDITOR_VIEW * view)53 void ViewEndSelectionChange(EDITOR_VIEW *view)
54 // The selection in this view has been changed, update the view
55 {
56 	SELECTION_UNIVERSE
57 		*finalSelection;
58 
59 	if(view->heldSelection)										// make sure we did not fail to create this at the start
60 	{
61 		if((finalSelection=GetSelectionInView(view,view->parentBuffer->selectionUniverse)))	// get selection that intersects view
62 		{
63 			XorSelectionUniverse(view->heldSelection,finalSelection);
64 			InvalidateViewSelection(view,finalSelection);
65 			CloseSelectionUniverse(finalSelection);				// get rid of this
66 		}
67 		CloseSelectionUniverse(view->heldSelection);			// get rid of memory this occupies
68 	}
69 	UpdateEditorWindows();
70 
71 	ViewEndChange(view);
72 
73 	if(view->viewSelectionChangedVector)						// see if someone needs to be called because of the change
74 	{
75 		view->viewSelectionChangedVector(view);					// call him
76 	}
77 }
78 
ViewStartSelectionChange(EDITOR_VIEW * view)79 void ViewStartSelectionChange(EDITOR_VIEW *view)
80 // The selection in this view is about to change, so prepare for it
81 // This copies the visible part of the current selection, and compares
82 // it to the updated version when the end function is called
83 {
84 	view->heldSelection=GetSelectionInView(view,view->parentBuffer->selectionUniverse);	// get a selection universe, use it to work out what changes are about to occur
85 	ViewStartChange(view);
86 }
87 
ViewEndMarkChange(MARK_VISIBILITY * visibility)88 void ViewEndMarkChange(MARK_VISIBILITY *visibility)
89 // A visible mark in this view has been changed, update the view
90 {
91 	SELECTION_UNIVERSE
92 		*finalSelection;
93 
94 	if(visibility->heldMark)									// make sure we did not fail to create this at the start
95 	{
96 		if((finalSelection=GetSelectionInView(visibility->parentView,visibility->parentMark->selectionUniverse)))	// work out where the mark is now
97 		{
98 			XorSelectionUniverse(visibility->heldMark,finalSelection);
99 			InvalidateViewSelection(visibility->parentView,finalSelection);
100 			CloseSelectionUniverse(finalSelection);				// get rid of this
101 		}
102 		CloseSelectionUniverse(visibility->heldMark);			// get rid of memory this occupies
103 	}
104 	UpdateEditorWindows();
105 
106 	ViewEndChange(visibility->parentView);
107 }
108 
ViewStartMarkChange(MARK_VISIBILITY * visibility)109 void ViewStartMarkChange(MARK_VISIBILITY *visibility)
110 // A visible mark in this view is about to change, so prepare for it
111 {
112 	visibility->heldMark=GetSelectionInView(visibility->parentView,visibility->parentMark->selectionUniverse);	// get a selection universe, use it to work out what changes are about to occur
113 	ViewStartChange(visibility->parentView);
114 }
115 
ViewEndStyleAttributeChange(EDITOR_VIEW * view)116 void ViewEndStyleAttributeChange(EDITOR_VIEW *view)
117 // The attributes of styles in view have finished changing
118 {
119 	ViewStyleFontsChanged(view);
120 	InvalidateView(view);									// this is pretty lazy
121 }
122 
ViewStartStyleAttributeChange(EDITOR_VIEW * view)123 void ViewStartStyleAttributeChange(EDITOR_VIEW *view)
124 // The attributes of styles in the view are being changed
125 {
126 }
127 
ViewEndStyleChange(EDITOR_VIEW * view)128 void ViewEndStyleChange(EDITOR_VIEW *view)
129 // The styles applied the text for this view have been changed, invalidate the view
130 {
131 	UINT32
132 		topLine,
133 		numLines;
134 	INT32
135 		leftPixel,
136 		xPosition;
137 	UINT32
138 		slopLeft,
139 		slopRight;
140 	UINT32
141 		numPixels;
142 	CHUNK_HEADER
143 		*chunk;
144 	UINT32
145 		offset,
146 		currentPosition;
147 	UINT32
148 		lineLength,
149 		maxPosition;
150 	UINT32
151 		oldStyleStart,
152 		newStyleStart;
153 	UINT32
154 		oldStyleElements,
155 		newStyleElements;
156 	UINT32
157 		oldStyle,
158 		newStyle;
159 	bool
160 		hadOldStyle,
161 		hadNewStyle;
162 	UINT32
163 		i;
164 	bool
165 		done;
166 
167 	if(view->heldStyle)										// make sure we did not fail to create this at the start
168 	{
169 		GetEditorViewTextInfo(view,&topLine,&numLines,&leftPixel,&numPixels);
170 		done=false;
171 		for(i=0;!done&&(i<numLines);i++)					// add invalidations a line at a time
172 		{
173 			LineToChunkPosition(view->parentBuffer->textUniverse,topLine+i,&chunk,&offset,&currentPosition);	// get position of top line in this view
174 			ChunkPositionToNextLine(view->parentBuffer->textUniverse,chunk,offset,&chunk,&offset,&lineLength);	// get length of this line
175 			maxPosition=currentPosition+lineLength;			// go no further than this looking for a style change in this line
176 
177 			while(!done&&(currentPosition<maxPosition))		// walk through the current line looking for a style change
178 			{
179 				hadOldStyle=GetStyleRange(view->heldStyle,currentPosition,&oldStyleStart,&oldStyleElements,&oldStyle);
180 				hadNewStyle=GetStyleRange(view->parentBuffer->styleUniverse,currentPosition,&newStyleStart,&newStyleElements,&newStyle);
181 
182 				if(hadOldStyle||hadNewStyle)				// make sure there are some changes to look at
183 				{
184 					if(oldStyle!=newStyle)					// is there a change?
185 					{
186 						// currentPosition now contains the location of the style change, invalidate to the end of the line
187 						xPosition=leftPixel+numPixels;		// don't look past here
188 						GetEditorViewTextToGraphicPosition(view,currentPosition,&xPosition,true,&slopLeft,&slopRight);
189 						if(xPosition>(INT32)slopLeft)
190 						{
191 							xPosition-=slopLeft;			// shift back to account for font overhang
192 						}
193 						else
194 						{
195 							xPosition=0;
196 						}
197 						if(xPosition<leftPixel)
198 						{
199 							xPosition=leftPixel;
200 						}
201 						xPosition-=leftPixel;				// make relative to scrolled view
202 						if(xPosition<(INT32)numPixels)		// work to do?
203 						{
204 							InvalidateViewPortion(view,i,i+1,xPosition,numPixels);	// invalidate to the end of the view
205 						}
206 						currentPosition=maxPosition;		// done with this line
207 					}
208 					else
209 					{
210 						// move forward to the nearest change
211 						if(hadOldStyle)						// see if we had an old style
212 						{
213 							currentPosition=oldStyleStart+oldStyleElements;
214 							if(hadNewStyle)					// if had new style too, see if it changes sooner
215 							{
216 								if(currentPosition>newStyleStart+newStyleElements)
217 								{
218 									currentPosition=newStyleStart+newStyleElements;
219 								}
220 							}
221 						}
222 						else								// no old style, so must have had new
223 						{
224 							currentPosition=newStyleStart+newStyleElements;
225 						}
226 					}
227 				}
228 				else
229 				{
230 					done=true;								// no styles defined here, so no changes
231 				}
232 			}
233 		}
234 		CloseStyleUniverse(view->heldStyle);				// get rid of memory this occupies
235 	}
236 	UpdateEditorWindows();
237 	ViewEndChange(view);
238 }
239 
ViewStartStyleChange(EDITOR_VIEW * view)240 void ViewStartStyleChange(EDITOR_VIEW *view)
241 // The styles applied to text in this view are about to change, so prepare for it
242 {
243 	UINT32
244 		topLine,
245 		numLines;
246 	INT32
247 		leftPixel;
248 	UINT32
249 		numPixels;
250 	CHUNK_HEADER
251 		*chunk;
252 	UINT32
253 		offset,
254 		startPosition,
255 		endPosition,
256 		actualStart,
257 		length;
258 	UINT32
259 		style;
260 	UINT32
261 		i;
262 	bool
263 		done;
264 
265 	if((view->heldStyle=OpenStyleUniverse()))			// get a style universe, and add the styles visible in this view to it
266 	{
267 		GetEditorViewTextInfo(view,&topLine,&numLines,&leftPixel,&numPixels);
268 		LineToChunkPosition(view->parentBuffer->textUniverse,topLine,&chunk,&offset,&startPosition);		// get position of top line in this view
269 		LineToChunkPosition(view->parentBuffer->textUniverse,topLine+numLines,&chunk,&offset,&endPosition);	// get position past last line in this view
270 		done=false;
271 		i=startPosition;
272 		while(i<endPosition&&!done)						// copy the part of the style array that intersects the view
273 		{
274 			if(GetStyleRange(view->parentBuffer->styleUniverse,i,&actualStart,&length,&style))
275 			{
276 				ForceStyleIntoRange(style);
277 				if(actualStart<endPosition)
278 				{
279 					if(actualStart+length>endPosition)
280 					{
281 						length=endPosition-actualStart;
282 					}
283 					SetStyleRange(view->heldStyle,actualStart,length,style);
284 					i=actualStart+length;
285 				}
286 				else
287 				{
288 					done=true;
289 				}
290 			}
291 			else
292 			{
293 				done=true;
294 			}
295 		}
296 	}
297 }
298 
ViewEndTabSizeChange(EDITOR_VIEW * view)299 void ViewEndTabSizeChange(EDITOR_VIEW *view)
300 // The tab size on the passed view has finished changing
301 {
302 	InvalidateView(view);								// this is pretty lazy
303 }
304 
ViewStartTabSizeChange(EDITOR_VIEW * view)305 void ViewStartTabSizeChange(EDITOR_VIEW *view)
306 // The tab size on the passed view is about to change
307 {
308 }
309 
ViewEndTextChange(EDITOR_VIEW * view)310 void ViewEndTextChange(EDITOR_VIEW *view)
311 // The text in view has finished being changed bring the view back
312 // up to date
313 {
314 	ViewEndChange(view);
315 	if(view->viewTextChangedVector)						// see if someone needs to be called because of the change
316 	{
317 		view->viewTextChangedVector(view);				// call him with my pointer
318 	}
319 }
320 
ViewStartTextChange(EDITOR_VIEW * view)321 void ViewStartTextChange(EDITOR_VIEW *view)
322 // The text in view is about to be changed in some way, do whatever is needed
323 // so that when ViewEndTextChange is called, the correct parts of the view are
324 // invalidated.
325 // NOTE: when the text changes, it is possible that the selection information
326 // will also change, so that updates will be handled correctly
327 {
328 	ViewStartChange(view);
329 }
330 
ViewEndActiveChange(EDITOR_VIEW * view)331 void ViewEndActiveChange(EDITOR_VIEW *view)
332 // View's active status is done changing
333 {
334 	ViewEndSelectionChange(view);
335 }
336 
ViewStartActiveChange(EDITOR_VIEW * view)337 void ViewStartActiveChange(EDITOR_VIEW *view)
338 // View's active status is changing
339 {
340 	ViewStartSelectionChange(view);
341 }
342 
UnSetViewStyleFont(EDITOR_VIEW * view,UINT32 style)343 static void UnSetViewStyleFont(EDITOR_VIEW *view,UINT32 style)
344 // Free the font currently in use by style of view
345 // NOTE: it is a bad idea to call this for the default style until the window
346 // will no longer be used, since the default is used when the given style
347 // is not available
348 {
349 	if(view->viewStyles[style].font)
350 	{
351 		FreeEditorFont(view->viewStyles[style].font);
352 		view->viewStyles[style].font=NULL;				// mark this font as unused
353 	}
354 }
355 
SetViewStyleFont(EDITOR_VIEW * view,UINT32 style,char * fontName)356 static bool SetViewStyleFont(EDITOR_VIEW *view,UINT32 style,char *fontName)
357 // Update the font used for a style in view
358 // NOTE: it is necessary to call RecalculateViewFontInfo
359 // after calling this (that is left to the caller, since he may need to make
360 // many calls to this in a row and the recalculation can be left until after
361 // the last call)
362 {
363 	EDITOR_FONT
364 		*newFont;
365 
366 	if((newFont=LoadEditorFont(fontName)))
367 	{
368 		UnSetViewStyleFont(view,style);					// get rid of old font that was there (if any)
369 		view->viewStyles[style].font=newFont;
370 		return(true);
371 	}
372 	return(false);
373 }
374 
SetViewTabSize(EDITOR_VIEW * view,UINT32 size)375 static void SetViewTabSize(EDITOR_VIEW *view,UINT32 size)
376 // set the tabSize for view
377 {
378 	if(size>255)
379 	{
380 		size=255;			// limit this
381 	}
382 	view->tabSize=size;
383 }
384 
UnInitializeViewStyles(EDITOR_VIEW * view)385 static void UnInitializeViewStyles(EDITOR_VIEW *view)
386 // get rid of style information tied to view
387 {
388 	UINT32
389 		i;
390 
391 	for(i=0;i<VIEW_MAX_STYLES;i++)
392 	{
393 		UnSetViewStyleFont(view,i);
394 	}
395 }
396 
InitializeViewStyles(EDITOR_VIEW * view,EDITOR_VIEW_DESCRIPTOR * descriptor)397 static bool InitializeViewStyles(EDITOR_VIEW *view,EDITOR_VIEW_DESCRIPTOR *descriptor)
398 // initialize style information for view
399 {
400 	UINT32
401 		i;
402 
403 	for(i=0;i<VIEW_MAX_STYLES;i++)
404 	{
405 		view->viewStyles[i].font=NULL;					// clear pointer
406 		view->viewStyles[i].haveForegroundColor=false;	// no colors defined yet
407 		view->viewStyles[i].haveBackgroundColor=false;
408 	}
409 
410 	// set up default style (which must be present)
411 	view->viewStyles[0].foregroundColor=descriptor->foregroundColor;
412 	view->viewStyles[0].haveForegroundColor=true;
413 
414 	view->viewStyles[0].backgroundColor=descriptor->backgroundColor;
415 	view->viewStyles[0].haveBackgroundColor=true;
416 
417 	if(SetViewStyleFont(view,0,descriptor->fontName))
418 	{
419 		return(true);
420 	}
421 	return(false);
422 }
423 
GetEditorViewTabSize(EDITOR_VIEW * view)424 UINT32 GetEditorViewTabSize(EDITOR_VIEW *view)
425 // get the current tab size for the given view
426 {
427 	return(view->tabSize);
428 }
429 
SetEditorViewTabSize(EDITOR_VIEW * view,UINT32 size)430 bool SetEditorViewTabSize(EDITOR_VIEW *view,UINT32 size)
431 // set the tab size to be used in view
432 // if there is a problem, leave the tab size unchanged, set the error
433 // and return false
434 {
435 	ViewStartTabSizeChange(view);
436 	SetViewTabSize(view,size);
437 	ViewEndTabSizeChange(view);
438 	return(true);
439 }
440 
ForceStyleRange(UINT32 * style)441 static void ForceStyleRange(UINT32 *style)
442 // make sure the style is in range (for externally called routines)
443 {
444 	if(*style>=VIEW_MAX_STYLES)
445 	{
446 		*style=VIEW_MAX_STYLES-1;
447 	}
448 }
449 
GetEditorViewStyleFont(EDITOR_VIEW * view,UINT32 style,char * font,UINT32 stringBytes)450 bool GetEditorViewStyleFont(EDITOR_VIEW *view,UINT32 style,char *font,UINT32 stringBytes)
451 // get the font that is in use in view for the given style
452 // if the font will not fit within string bytes, return false
453 // if there is no font in use, return an empty string
454 {
455 	ForceStyleRange(&style);
456 	if(stringBytes)
457 	{
458 		if(view->viewStyles[style].font)
459 		{
460 			GetEditorFontName(view->viewStyles[style].font,font,stringBytes);
461 			return(true);
462 		}
463 		else
464 		{
465 			font[0]='\0';
466 			return(true);
467 		}
468 	}
469 	return(false);
470 }
471 
SetEditorViewStyleFont(EDITOR_VIEW * view,UINT32 style,char * font)472 bool SetEditorViewStyleFont(EDITOR_VIEW *view,UINT32 style,char *font)
473 // set the font to be used in view
474 // this will force an update of view
475 // if there is a problem, leave the window font unchanged, set the error
476 // and return false
477 {
478 	bool
479 		result;
480 
481 	result=false;
482 	ForceStyleRange(&style);
483 	ViewStartStyleAttributeChange(view);
484 	if(SetViewStyleFont(view,style,font))				// set new font
485 	{
486 		result=true;
487 	}
488 	ViewEndStyleAttributeChange(view);
489 	return(result);
490 }
491 
ClearEditorViewStyleFont(EDITOR_VIEW * view,UINT32 style)492 void ClearEditorViewStyleFont(EDITOR_VIEW *view,UINT32 style)
493 // clear the font to be used for style in view
494 // this will force an update of view
495 {
496 	ForceStyleRange(&style);
497 	ViewStartStyleAttributeChange(view);
498 	UnSetViewStyleFont(view,style);
499 	ViewEndStyleAttributeChange(view);
500 }
501 
GetEditorViewStyleForegroundColor(EDITOR_VIEW * view,UINT32 style,EDITOR_COLOR * foregroundColor)502 bool GetEditorViewStyleForegroundColor(EDITOR_VIEW *view,UINT32 style,EDITOR_COLOR *foregroundColor)
503 // get the foreground color in use by style of view
504 // if the style does not have a foreground color associated with it, return false
505 {
506 	ForceStyleRange(&style);
507 	if(view->viewStyles[style].haveForegroundColor)
508 	{
509 		*foregroundColor=view->viewStyles[style].foregroundColor;	// get pixel of foreground for this style
510 		return(true);
511 	}
512 	return(false);
513 }
514 
SetEditorViewStyleForegroundColor(EDITOR_VIEW * view,UINT32 style,EDITOR_COLOR foregroundColor)515 bool SetEditorViewStyleForegroundColor(EDITOR_VIEW *view,UINT32 style,EDITOR_COLOR foregroundColor)
516 // set the foreground color to be used by style of view
517 // this will force an update of view
518 // if there is a problem, leave the color unchanged, set the error
519 // and return false
520 {
521 	ForceStyleRange(&style);
522 	ViewStartStyleAttributeChange(view);
523 	view->viewStyles[style].foregroundColor=foregroundColor;
524 	view->viewStyles[style].haveForegroundColor=true;
525 	ViewEndStyleAttributeChange(view);
526 	return(true);
527 }
528 
ClearEditorViewStyleForegroundColor(EDITOR_VIEW * view,UINT32 style)529 void ClearEditorViewStyleForegroundColor(EDITOR_VIEW *view,UINT32 style)
530 // clear the foreground color to be used for style in view
531 // this will force an update of view
532 {
533 	ForceStyleRange(&style);
534 	ViewStartStyleAttributeChange(view);
535 	view->viewStyles[style].haveForegroundColor=false;
536 	ViewEndStyleAttributeChange(view);
537 }
538 
GetEditorViewStyleBackgroundColor(EDITOR_VIEW * view,UINT32 style,EDITOR_COLOR * backgroundColor)539 bool GetEditorViewStyleBackgroundColor(EDITOR_VIEW *view,UINT32 style,EDITOR_COLOR *backgroundColor)
540 // get the background color in use by style of view
541 // if the style does not have a background color associated with it, return false
542 {
543 	ForceStyleRange(&style);
544 	if(view->viewStyles[style].haveBackgroundColor)
545 	{
546 		*backgroundColor=view->viewStyles[style].backgroundColor;	// get pixel of background for this style
547 		return(true);
548 	}
549 	return(false);
550 }
551 
SetEditorViewStyleBackgroundColor(EDITOR_VIEW * view,UINT32 style,EDITOR_COLOR backgroundColor)552 bool SetEditorViewStyleBackgroundColor(EDITOR_VIEW *view,UINT32 style,EDITOR_COLOR backgroundColor)
553 // set the background color to be used by style of view
554 // this will force an update of view
555 // if there is a problem, leave the color unchanged, set the error
556 // and return false
557 {
558 	ForceStyleRange(&style);
559 	ViewStartStyleAttributeChange(view);
560 	view->viewStyles[style].backgroundColor=backgroundColor;
561 	view->viewStyles[style].haveBackgroundColor=true;
562 	ViewEndStyleAttributeChange(view);
563 	return(true);
564 }
565 
ClearEditorViewStyleBackgroundColor(EDITOR_VIEW * view,UINT32 style)566 void ClearEditorViewStyleBackgroundColor(EDITOR_VIEW *view,UINT32 style)
567 // clear the background color to be used for style in view
568 // this will force an update of view
569 {
570 	ForceStyleRange(&style);
571 	ViewStartStyleAttributeChange(view);
572 	view->viewStyles[style].haveBackgroundColor=false;
573 	ViewEndStyleAttributeChange(view);
574 }
575 
GetEditorViewSelectionForegroundColor(EDITOR_VIEW * view,EDITOR_COLOR * foregroundColor)576 bool GetEditorViewSelectionForegroundColor(EDITOR_VIEW *view,EDITOR_COLOR *foregroundColor)
577 // get the foreground color in use by the selection of view
578 // NOTE: it is possible that no color has been specified.
579 // If that is the case, this will return false
580 {
581 	if(view->haveSelectionForegroundColor)
582 	{
583 		*foregroundColor=view->selectionForegroundColor;
584 		return(true);
585 	}
586 	return(false);
587 }
588 
SetEditorViewSelectionForegroundColor(EDITOR_VIEW * view,EDITOR_COLOR foregroundColor)589 bool SetEditorViewSelectionForegroundColor(EDITOR_VIEW *view,EDITOR_COLOR foregroundColor)
590 // set the foreground color to be used for selections in view
591 // this will force an update of view
592 // if there is a problem, leave the color unchanged, set the error
593 // and return false
594 // NOTE: if haveForeground is false, this will clear the foreground color
595 // making the selection draw the foreground as the inverse of the current
596 // color
597 {
598 	view->selectionForegroundColor=foregroundColor;
599 	view->haveSelectionForegroundColor=true;
600 	InvalidateViewSelection(view,view->parentBuffer->selectionUniverse);
601 	return(true);
602 }
603 
ClearEditorViewSelectionForegroundColor(EDITOR_VIEW * view)604 void ClearEditorViewSelectionForegroundColor(EDITOR_VIEW *view)
605 // Clear the foreground color, making the selection draw the foreground
606 // as the inverse of the current color
607 {
608 	view->haveSelectionForegroundColor=false;
609 	InvalidateViewSelection(view,view->parentBuffer->selectionUniverse);
610 }
611 
GetEditorViewSelectionBackgroundColor(EDITOR_VIEW * view,EDITOR_COLOR * backgroundColor)612 bool GetEditorViewSelectionBackgroundColor(EDITOR_VIEW *view,EDITOR_COLOR *backgroundColor)
613 // get the background color in use by the selection of view
614 // NOTE: it is possible that no color has been specified.
615 // If that is the case, this will return false
616 {
617 	if(view->haveSelectionBackgroundColor)
618 	{
619 		*backgroundColor=view->selectionBackgroundColor;
620 		return(true);
621 	}
622 	return(false);
623 }
624 
SetEditorViewSelectionBackgroundColor(EDITOR_VIEW * view,EDITOR_COLOR backgroundColor)625 bool SetEditorViewSelectionBackgroundColor(EDITOR_VIEW *view,EDITOR_COLOR backgroundColor)
626 // set the background color to be used for selections in view
627 // this will force an update of view
628 // if there is a problem, leave the color unchanged, set the error
629 // and return false
630 // NOTE: if haveBackground is false, this will clear the background color
631 // making the selection draw the background as the inverse of the current
632 // color
633 {
634 	view->selectionBackgroundColor=backgroundColor;
635 	view->haveSelectionBackgroundColor=true;
636 	InvalidateViewSelection(view,view->parentBuffer->selectionUniverse);
637 	return(true);
638 }
639 
ClearEditorViewSelectionBackgroundColor(EDITOR_VIEW * view)640 void ClearEditorViewSelectionBackgroundColor(EDITOR_VIEW *view)
641 // Clear the background color, making the selection draw the background
642 // as the inverse of the current color
643 {
644 	view->haveSelectionBackgroundColor=false;
645 	InvalidateViewSelection(view,view->parentBuffer->selectionUniverse);
646 }
647 
ViewsEndSelectionChange(EDITOR_BUFFER * buffer)648 void ViewsEndSelectionChange(EDITOR_BUFFER *buffer)
649 // The selection in buffer has finished being changed
650 // do whatever needs to be done
651 // to get it up to date
652 {
653 	EDITOR_VIEW
654 		*currentView;
655 
656 	currentView=buffer->firstView;
657 	while(currentView)									// walk through all views, update each one as needed
658 	{
659 		ViewEndSelectionChange(currentView);
660 		currentView=currentView->nextBufferView;		// locate next view of this buffer
661 	}
662 }
663 
ViewsStartSelectionChange(EDITOR_BUFFER * buffer)664 void ViewsStartSelectionChange(EDITOR_BUFFER *buffer)
665 // The selection in buffer are about to be changed in some way, do whatever is needed
666 // NOTE: a change in the selection could mean something as simple as a cursor position change
667 // NOTE also: selection changes cannot be nested, and nothing except the selection is allowed
668 // to be altered during a selection change
669 {
670 	EDITOR_VIEW
671 		*currentView;
672 
673 	currentView=buffer->firstView;
674 	while(currentView)									// walk through all views, update each one as needed
675 	{
676 		ViewStartSelectionChange(currentView);
677 		currentView=currentView->nextBufferView;		// locate next view of this buffer
678 	}
679 }
680 
ViewInvalidateMark(EDITOR_VIEW * view,EDITOR_MARK * mark)681 void ViewInvalidateMark(EDITOR_VIEW *view,EDITOR_MARK *mark)
682 // Invalidate the selection of the passed mark in the passed view
683 {
684 	InvalidateViewSelection(view,mark->selectionUniverse);
685 }
686 
ViewsInvalidateMark(EDITOR_MARK * mark)687 void ViewsInvalidateMark(EDITOR_MARK *mark)
688 // Invalidate the selection of the passed mark in all visible views
689 {
690 	MARK_VISIBILITY
691 		*currentVisibility;
692 
693 	currentVisibility=mark->headVisibility;
694 	while(currentVisibility)							// walk through all views, update each one as needed
695 	{
696 		ViewInvalidateMark(currentVisibility->parentView,mark);
697 		currentVisibility=currentVisibility->nextView;	// locate next view this mark is visible in
698 	}
699 }
700 
ViewsEndMarkChange(EDITOR_MARK * mark)701 void ViewsEndMarkChange(EDITOR_MARK *mark)
702 // The passed mark has finished being changed, update all
703 // affected views.
704 {
705 	MARK_VISIBILITY
706 		*currentVisibility;
707 
708 	currentVisibility=mark->headVisibility;
709 	while(currentVisibility)							// walk through all views, update each one as needed
710 	{
711 		ViewEndMarkChange(currentVisibility);
712 		currentVisibility=currentVisibility->nextView;	// locate next view this mark is visible in
713 	}
714 }
715 
ViewsStartMarkChange(EDITOR_MARK * mark)716 void ViewsStartMarkChange(EDITOR_MARK *mark)
717 // Marks (which may be visible) in buffer are about to be changed in some way, do whatever is needed
718 // NOTE: mark changes cannot be nested, and nothing except a mark is allowed
719 // to be altered during a mark change
720 {
721 	MARK_VISIBILITY
722 		*currentVisibility;
723 
724 	currentVisibility=mark->headVisibility;
725 	while(currentVisibility)							// walk through all views, update each one as needed
726 	{
727 		ViewStartMarkChange(currentVisibility);
728 		currentVisibility=currentVisibility->nextView;	// locate next view this mark is visible in
729 	}
730 }
731 
ViewsStartStyleChange(EDITOR_BUFFER * buffer)732 void ViewsStartStyleChange(EDITOR_BUFFER *buffer)
733 // The style in buffer is about to be changed in some way, do whatever is needed
734 // NOTE also: style changes cannot be nested, and nothing except the style is allowed
735 // to be altered during a style change
736 {
737 	EDITOR_VIEW
738 		*currentView;
739 
740 	currentView=buffer->firstView;
741 	while(currentView)									// walk through all views, update each one as needed
742 	{
743 		ViewStartStyleChange(currentView);
744 		currentView=currentView->nextBufferView;		// locate next view of this buffer
745 	}
746 }
747 
ViewsEndStyleChange(EDITOR_BUFFER * buffer)748 void ViewsEndStyleChange(EDITOR_BUFFER *buffer)
749 // The style in buffer has finished being changed
750 // do whatever needs to be done to get it up to date
751 {
752 	EDITOR_VIEW
753 		*currentView;
754 
755 	currentView=buffer->firstView;
756 	while(currentView)									// walk through all views, update each one as needed
757 	{
758 		ViewEndStyleChange(currentView);
759 		currentView=currentView->nextBufferView;		// locate next view of this buffer
760 	}
761 }
762 
ViewsStartTextChange(EDITOR_BUFFER * buffer)763 void ViewsStartTextChange(EDITOR_BUFFER *buffer)
764 // The text in buffer is about to be changed in some way, do whatever is needed
765 // NOTE: when the text changes, it is possible that the selection information
766 // will also change, so that updates will be handled correctly
767 {
768 	EDITOR_VIEW
769 		*currentView;
770 
771 	currentView=buffer->firstView;
772 	while(currentView)									// walk through all views, update each one as needed
773 	{
774 		ViewStartTextChange(currentView);
775 		currentView=currentView->nextBufferView;		// locate next view of this buffer
776 	}
777 }
778 
ViewsEndTextChange(EDITOR_BUFFER * buffer)779 void ViewsEndTextChange(EDITOR_BUFFER *buffer)
780 // The text in buffer has finished being changed, and the views have been
781 // updated, do whatever needs to be done
782 {
783 	EDITOR_VIEW
784 		*currentView;
785 
786 	currentView=buffer->firstView;
787 	while(currentView)									// walk through all views, update each one as needed
788 	{
789 		ViewEndTextChange(currentView);
790 		currentView=currentView->nextBufferView;		// locate next view of this buffer
791 	}
792 }
793 
EditorActivateView(EDITOR_VIEW * view)794 void EditorActivateView(EDITOR_VIEW *view)
795 // activate view (this is not nestable)
796 {
797 	ViewStartActiveChange(view);
798 	view->active=true;
799 	ViewEndActiveChange(view);
800 }
801 
EditorDeactivateView(EDITOR_VIEW * view)802 void EditorDeactivateView(EDITOR_VIEW *view)
803 // deactivate view (this is not nestable)
804 {
805 	ViewStartActiveChange(view);
806 	view->active=false;
807 	ViewEndActiveChange(view);
808 }
809 
DisposeEditorView(EDITOR_VIEW * view)810 void DisposeEditorView(EDITOR_VIEW *view)
811 // unlink view from everywhere, and dispose of it
812 {
813 	DisposeViewInfo(view);							// tell GUI to tear it down
814 	UnInitializeViewStyles(view);					// get rid of style information for view
815 	UnlinkVisibleMarksFromView(view);				// get rid of any visible marks hanging off the view
816 	UnlinkViewFromBuffer(view);
817 	MDisposePtr(view);
818 }
819 
CreateEditorView(EDITOR_WINDOW * window,EDITOR_VIEW_DESCRIPTOR * descriptor)820 EDITOR_VIEW *CreateEditorView(EDITOR_WINDOW *window,EDITOR_VIEW_DESCRIPTOR *descriptor)
821 // create a view in window using descriptor
822 // if there is a problem, SetError, and return NULL
823 {
824 	EDITOR_VIEW
825 		*view;
826 
827 	if((view=(EDITOR_VIEW *)MNewPtr(sizeof(EDITOR_VIEW))))
828 	{
829 		LinkViewToBuffer(view,descriptor->buffer);
830 		view->parentWindow=window;
831 		view->active=descriptor->active;
832 		view->wantHome=false;
833 		SetViewTabSize(view,descriptor->tabSize);	// set, and limit the tab size
834 		view->haveSelectionForegroundColor=false;	// select by inverting text colors by default
835 		view->haveSelectionBackgroundColor=false;
836 		view->headVisibility=NULL;					// no visible marks hanging off of this view yet
837 		view->tailVisibility=NULL;
838 		view->viewTextChangedVector=descriptor->viewTextChangedVector;
839 		view->viewSelectionChangedVector=descriptor->viewSelectionChangedVector;
840 		view->viewPositionChangedVector=descriptor->viewPositionChangedVector;
841 
842 		if(InitializeViewStyles(view,descriptor))
843 		{
844 			if(CreateViewInfo(view,descriptor))
845 			{
846 				return(view);
847 			}
848 		}
849 		UnlinkViewFromBuffer(view);
850 		MDisposePtr(view);
851 	}
852 	return(NULL);
853 }
854