CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

LIST.H (21114B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /* $Header: /CounterStrike/LIST.H 1     3/03/97 10:25a Joe_bostic $ */
     17 /***********************************************************************************************
     18  ***              C O N F I D E N T I A L  ---  W E S T W O O D  S T U D I O S               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer                                            *
     22  *                                                                                             *
     23  *                    File Name : LIST.H                                                       *
     24  *                                                                                             *
     25  *                   Programmer : Joe L. Bostic                                                *
     26  *                                                                                             *
     27  *                   Start Date : 01/15/95                                                     *
     28  *                                                                                             *
     29  *                  Last Update : January 15, 1995 [JLB]                                       *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Functions:                                                                                  *
     33  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     34 
     35 #ifndef LIST_H
     36 #define LIST_H
     37 
     38 #include "control.h"
     39 #include "shapebtn.h"
     40 #include "slider.h"
     41 
     42 
     43 /***************************************************************************
     44  * ListClass -- Like a Windows ListBox structure									*
     45  *                                                                         *
     46  * INPUT:      int x -- x position of gadget											*
     47  *					int y -- y position of gadget											*
     48  *					int w -- width of gadget												*
     49  *					int h -- height of gadget												*
     50  *					UWORD flags -- see enumeration choices								*
     51  *                                                                         *
     52  * OUTPUT:     none.																			*
     53  * WARNINGS:														   						*
     54  * HISTORY:    01/03/1995 MML : Created.                                   *
     55  *=========================================================================*/
     56 class ListClass : public ControlClass
     57 {
     58 	public:
     59 		ListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down);
     60 		ListClass(ListClass const & list);
     61 		virtual ~ListClass(void);
     62 
     63 		virtual int Add_Item(char const * text);
     64 		virtual int Add_Item(int text);
     65 		virtual int Add_Scroll_Bar(void);
     66 		virtual void Bump(int up);
     67 		virtual int Count(void) const {return List.Count();};
     68 		virtual int Current_Index(void) const;
     69 		virtual char const * Current_Item(void) const;
     70 		virtual int Draw_Me(int forced);
     71 		virtual char const * Get_Item(int index) const;
     72 		virtual int Step_Selected_Index(int forward);
     73 		virtual void Flag_To_Redraw(void);
     74 
     75 		virtual void Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom);
     76 		virtual void Remove_Item(char const * text);
     77 		virtual void Remove_Item(int);
     78 		virtual int  Remove_Scroll_Bar(void);
     79 		virtual void Set_Selected_Index(int index);
     80 		virtual void Set_Selected_Index(char const * text);
     81 		virtual void Set_Tabs(int const * tabs);
     82 		virtual int  Set_View_Index(int index);
     83 		virtual void Step(int up);
     84 		virtual void Set_Position(int x, int y);
     85 
     86 		/*
     87 		** These overloaded list routines handle adding/removing the scroll bar
     88 		** automatically when the list box is added or removed.
     89 		*/
     90 		virtual LinkClass & Add(LinkClass & object);
     91 		virtual LinkClass & Add_Tail(LinkClass & object);
     92 		virtual LinkClass & Add_Head(LinkClass & object);
     93 		virtual GadgetClass * Remove(void);
     94 
     95 	protected:
     96 		virtual int  Action(unsigned flags, KeyNumType &key);
     97 		virtual void Draw_Entry(int index, int x, int y, int width, int selected);
     98 
     99 		/*
    100 		**	This controls what the text looks like. It uses the basic TPF_ flags that
    101 		**	are used to control Fancy_Text_Print().
    102 		*/
    103 		TextPrintType TextFlags;
    104 
    105 		/*
    106 		**	This is a series of tabstop pixel positions to use when processing any
    107 		**	<TAB> characters found in a list box string. The tabs are a series of
    108 		**	pixel offsets from the starting pixel position of the text.
    109 		*/
    110 		int const *Tabs;
    111 
    112 		/*
    113 		**	The actual list of text pointers is maintained by this list manager. The pointers
    114 		**	are stored in EMS. The text that is pointed to may also be in EMS.
    115 		*/
    116 		DynamicVectorClass<char const *> List;
    117 
    118 		/*
    119 		**	This is the total pixel height of a standard line of text. This is greatly
    120 		**	influenced by the TextFlags value.
    121 		*/
    122 		int LineHeight;
    123 
    124 		/*
    125 		**	This is the number of text lines that can fit within the list box.
    126 		*/
    127 		int LineCount;
    128 
    129 		/*
    130 		**	If the slider bar has been created, these point to the respective gadgets
    131 		**	that it is composed of.
    132 		*/
    133 		unsigned IsScrollActive:1;
    134 		ShapeButtonClass UpGadget;
    135 		ShapeButtonClass DownGadget;
    136 		SliderClass ScrollGadget;
    137 
    138 		/*
    139 		**	This is the currently selected index. It is highlighted.
    140 		*/
    141 		int SelectedIndex;
    142 
    143 		/*
    144 		**	This specifies the line (index) that is at the top of the list box.
    145 		*/
    146 		int CurrentTopIndex;
    147 };
    148 
    149 
    150 template<class T>
    151 class TListClass : public ControlClass
    152 {
    153 	public:
    154 		TListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down);
    155 		TListClass(TListClass<T> const & list);
    156 		virtual ~TListClass(void);
    157 		T operator [] (int index) const {return(List[index]);};
    158 		T & operator [] (int index) {return(List[index]);};
    159 
    160 		virtual int Add_Item(T text);
    161 		virtual int Add_Scroll_Bar(void);
    162 		virtual void Insert_Item(T item);
    163 		virtual void Bump(int up);
    164 		virtual int Count(void) const {return List.Count();};
    165 		virtual int Current_Index(void) const;
    166 		virtual T Current_Item(void) const;
    167 		virtual int Draw_Me(int forced);
    168 		virtual int Step_Selected_Index(int forward);
    169 		virtual void Flag_To_Redraw(void);
    170 		virtual T Get_Item(int index) const {return(List[index]);};
    171 
    172 		virtual void Peer_To_Peer(unsigned flags, KeyNumType & key, ControlClass & whom);
    173 		virtual void Remove_Item(T);
    174 		virtual void Remove_Index(int);
    175 		virtual int  Remove_Scroll_Bar(void);
    176 		virtual void Set_Selected_Index(int index);
    177 		virtual void Set_Selected_Index(T item);
    178 		virtual void Set_Tabs(int const * tabs);
    179 		virtual int  Set_View_Index(int index);
    180 		virtual void Step(int up);
    181 		virtual void Set_Position(int x, int y);
    182 
    183 		/*
    184 		** These overloaded list routines handle adding/removing the scroll bar
    185 		** automatically when the list box is added or removed.
    186 		*/
    187 		virtual LinkClass & Add(LinkClass & object);
    188 		virtual LinkClass & Add_Tail(LinkClass & object);
    189 		virtual LinkClass & Add_Head(LinkClass & object);
    190 		virtual GadgetClass * Remove(void);
    191 
    192 	protected:
    193 		virtual int  Action(unsigned flags, KeyNumType &key);
    194 
    195 		/*
    196 		**	This controls what the text looks like. It uses the basic TPF_ flags that
    197 		**	are used to control Fancy_Text_Print().
    198 		*/
    199 		TextPrintType TextFlags;
    200 
    201 		/*
    202 		**	This is a series of tabstop pixel positions to use when processing any
    203 		**	<TAB> characters found in a list box string. The tabs are a series of
    204 		**	pixel offsets from the starting pixel position of the text.
    205 		*/
    206 		int const * Tabs;
    207 
    208 		/*
    209 		**	The actual list of text pointers is maintained by this list manager.
    210 		*/
    211 		DynamicVectorClass<T> List;
    212 
    213 		/*
    214 		**	This is the total pixel height of a standard line of text. This is greatly
    215 		**	influenced by the TextFlags value.
    216 		*/
    217 		int LineHeight;
    218 
    219 		/*
    220 		**	This is the number of text lines that can fit within the list box.
    221 		*/
    222 		int LineCount;
    223 
    224 		/*
    225 		**	If the slider bar has been created, these point to the respective gadgets
    226 		**	that it is composed of.
    227 		*/
    228 		unsigned IsScrollActive:1;
    229 		ShapeButtonClass UpGadget;
    230 		ShapeButtonClass DownGadget;
    231 		SliderClass ScrollGadget;
    232 
    233 		/*
    234 		**	This is the currently selected index. It is highlighted.
    235 		*/
    236 		int SelectedIndex;
    237 
    238 		/*
    239 		**	This specifies the line (index) that is at the top of the list box.
    240 		*/
    241 		int CurrentTopIndex;
    242 };
    243 
    244 template<class T>
    245 TListClass<T>::TListClass(int id, int x, int y, int w, int h, TextPrintType flags, void const * up, void const * down) :
    246 	ControlClass(id, x, y, w, h, LEFTPRESS | LEFTRELEASE | KEYBOARD, false),
    247 	UpGadget(0, up, x+w, y),
    248 	DownGadget(0, down, x+w, y+h),
    249 	ScrollGadget(0, x+w, y, 0, h, true),
    250 	TextFlags(flags),
    251 	Tabs(0),
    252 	IsScrollActive(false),
    253 	SelectedIndex(0),
    254 	CurrentTopIndex(0)
    255 {
    256 	/*
    257 	**	Set preliminary values for the slider related gadgets. They don't automatically
    258 	**	appear at this time, but there are some values that can be pre-filled in.
    259 	*/
    260 	UpGadget.X -= UpGadget.Width;
    261 	DownGadget.X -= DownGadget.Width;
    262 	DownGadget.Y -= DownGadget.Height;
    263 	ScrollGadget.X -= max(UpGadget.Width, DownGadget.Width);
    264 	ScrollGadget.Y = Y+UpGadget.Height;
    265 	ScrollGadget.Height -= UpGadget.Height + DownGadget.Height;
    266 	ScrollGadget.Width = max(UpGadget.Width, DownGadget.Width);
    267 
    268 	/*
    269 	**	Set the list box to a default state.
    270 	*/
    271 	Fancy_Text_Print(TXT_NONE, 0, 0, TBLACK, TBLACK, TextFlags);
    272 	LineHeight = FontHeight+FontYSpacing-1;
    273 	LineCount = (h-1) / LineHeight;
    274 }
    275 
    276 template<class T>
    277 TListClass<T>::TListClass(TListClass<T> const & list) :
    278 	ControlClass(list),
    279 	TextFlags(list.TextFlags),
    280 	Tabs(list.Tabs),
    281 	List(list.List),
    282 	LineHeight(list.LineHeight),
    283 	LineCount(list.LineCount),
    284 	IsScrollActive(list.IsScrollActive),
    285 	UpGadget(list.UpGadget),
    286 	DownGadget(list.DownGadget),
    287 	ScrollGadget(list.ScrollGadget),
    288 	SelectedIndex(list.SelectedIndex),
    289 	CurrentTopIndex(list.CurrentTopIndex)
    290 {
    291 	UpGadget.Make_Peer(*this);
    292 	DownGadget.Make_Peer(*this);
    293 	ScrollGadget.Make_Peer(*this);
    294 }
    295 
    296 template<class T>
    297 void TListClass<T>::Set_Position(int x, int y)
    298 {
    299 	UpGadget.X = x + Width - UpGadget.Width;
    300 	UpGadget.Y = y;
    301 	DownGadget.X = x + Width - DownGadget.Width;
    302 	DownGadget.Y = y + Height - DownGadget.Height;
    303 	ScrollGadget.X = x + Width - max(UpGadget.Width, DownGadget.Width);
    304 	ScrollGadget.Y = y + UpGadget.Height;
    305 	ScrollGadget.Height = Height - (UpGadget.Height + DownGadget.Height);
    306 	ScrollGadget.Width = max(UpGadget.Width, DownGadget.Width);
    307 }
    308 
    309 template<class T>
    310 TListClass<T>::~TListClass(void)
    311 {
    312 	Remove_Scroll_Bar();
    313 }
    314 
    315 template<class T>
    316 void TListClass<T>::Insert_Item(T item)
    317 {
    318 	if (Current_Index() >= Count()) {
    319 		List.Add(item);
    320 	} else {
    321 		List.Add(item);
    322 
    323 		/*
    324 		**	Move all trailing items upward.
    325 		*/
    326 		for (int index = List.Count()-1; index >= Current_Index(); index--) {
    327 			List[index+1] = List[index];
    328 		}
    329 
    330 		/*
    331 		**	Insert the new item into the location at the current index.
    332 		*/
    333 		List[Current_Index()] = item;
    334 	}
    335 }
    336 
    337 
    338 template<class T>
    339 int TListClass<T>::Add_Item(T text)
    340 {
    341 //	if (text) {
    342 		List.Add(text);
    343 		Flag_To_Redraw();
    344 
    345 		/*
    346 		**	Add scroll gadget if the list gets too large to display all of the items
    347 		**	at the same time.
    348 		*/
    349 		if (List.Count() > LineCount) {
    350 			Add_Scroll_Bar();
    351 		}
    352 
    353 		/*
    354 		**	Tell the slider that there is one more entry in the list.
    355 		*/
    356 		if (IsScrollActive) {
    357 			ScrollGadget.Set_Maximum(List.Count());
    358 		}
    359 //	}
    360 	return(List.Count() - 1);
    361 }
    362 
    363 template<class T>
    364 void TListClass<T>::Remove_Index(int index)
    365 {
    366 	if ((unsigned)index < List.Count()) {
    367 		List.Delete(index);
    368 
    369 		/*
    370 		**	If the list is now small enough to display completely within the list box region,
    371 		**	then delete the slider gadget (if they are present).
    372 		*/
    373 		if (List.Count() <= LineCount) {
    374 			Remove_Scroll_Bar();
    375 		}
    376 
    377 		/*
    378 		**	Tell the slider that there is one less entry in the list.
    379 		*/
    380 		if (IsScrollActive) {
    381 			ScrollGadget.Set_Maximum(List.Count());
    382 		}
    383 
    384 		/*
    385 		** If we just removed the selected entry, select the previous one
    386 		*/
    387 		if (SelectedIndex >= List.Count()) {
    388 			SelectedIndex--;
    389 			if (SelectedIndex < 0) {
    390 				SelectedIndex = 0;
    391 			}
    392 		}
    393 
    394 		/*
    395 		** If we just removed the top-displayed entry, step up one item
    396 		*/
    397 		if (CurrentTopIndex >= List.Count()) {
    398 			CurrentTopIndex--;
    399 			if (CurrentTopIndex < 0)
    400 				CurrentTopIndex = 0;
    401 			if (IsScrollActive)
    402 				ScrollGadget.Step(1);
    403 		}
    404 	}
    405 }
    406 
    407 template<class T>
    408 void TListClass<T>::Remove_Item(T text)
    409 {
    410 	Remove_Index(List.ID(text));
    411 }
    412 
    413 template<class T>
    414 int TListClass<T>::Action(unsigned flags, KeyNumType & key)
    415 {
    416 	if (flags & LEFTRELEASE) {
    417 		key = KN_NONE;
    418 		flags &= (~LEFTRELEASE);
    419 		ControlClass::Action(flags, key);
    420 		return(true);
    421 	} else {
    422 
    423 		/*
    424 		** Handle keyboard events here.
    425 		*/
    426 		if (flags & KEYBOARD) {
    427 
    428 			/*
    429 			**	Process the keyboard character. If indicated, consume this keyboard event
    430 			**	so that the edit gadget ID number is not returned.
    431 			*/
    432 			if (key == KN_UP) {
    433 				Step_Selected_Index(-1);
    434 				key = KN_NONE;
    435 			} else if (key == KN_DOWN) {
    436 				Step_Selected_Index(1);
    437 				key = KN_NONE;
    438 			} else {
    439 				flags &= ~KEYBOARD;
    440 			}
    441 
    442 		} else {
    443 
    444 			int index = Get_Mouse_Y() - (Y+1);
    445 			index = index / LineHeight;
    446 			SelectedIndex = CurrentTopIndex + index;
    447 			SelectedIndex = min(SelectedIndex, List.Count()-1);
    448 		}
    449 	}
    450 	return(ControlClass::Action(flags, key));
    451 }
    452 
    453 template<class T>
    454 int TListClass<T>::Draw_Me(int forced)
    455 {
    456 	if (GadgetClass::Draw_Me(forced)) {
    457 
    458 		/*
    459 		**	Turn off the mouse.
    460 		*/
    461 		if (LogicPage == &SeenBuff) {
    462 			Conditional_Hide_Mouse(X, Y, X+Width, Y+Height);
    463 		}
    464 
    465 		Draw_Box(X, Y, Width, Height, BOXSTYLE_BOX, true);
    466 
    467 		/*
    468 		**	Draw List.
    469 		*/
    470 		if (List.Count()) {
    471 			for (int index = 0; index < LineCount; index++)  {
    472 				int line = CurrentTopIndex + index;
    473 
    474 				if (List.Count() > line) {
    475 
    476 					/*
    477 					**	Prints the text and handles right edge clipping and tabs.
    478 					*/
    479 					List[line]->Draw_It(line, X+1, Y+(LineHeight*index)+1, Width-2, LineHeight, (line == SelectedIndex), TextFlags);
    480 //					List[index].Draw_It(line, X+1, Y+(LineHeight*index)+1, Width-2, LineHeight, (line == SelectedIndex), TextFlags);
    481 //					Draw_Entry(line, X+1, Y+(LineHeight*index)+1, Width-2, (line == SelectedIndex));
    482 				}
    483 			}
    484 		}
    485 
    486 		/*
    487 		**	Turn on the mouse.
    488 		*/
    489 		if (LogicPage == &SeenBuff) {
    490 			Conditional_Show_Mouse();
    491 		}
    492 		return(true);
    493 	}
    494 	return(false);
    495 }
    496 
    497 template<class T>
    498 void TListClass<T>::Bump(int up)
    499 {
    500 	if (IsScrollActive) {
    501 		if (ScrollGadget.Step(up)) {
    502 			CurrentTopIndex = ScrollGadget.Get_Value();
    503 			Flag_To_Redraw();
    504 		}
    505 	}
    506 }
    507 
    508 template<class T>
    509 void TListClass<T>::Step(int up)
    510 {
    511 	if (IsScrollActive) {
    512 		if (ScrollGadget.Step(up)) {
    513 			CurrentTopIndex = ScrollGadget.Get_Value();
    514 			Flag_To_Redraw();
    515 		}
    516 	}
    517 }
    518 
    519 #ifdef NEVER
    520 template<class T>
    521 T TListClass<T>::Get_Item(int index) const
    522 {
    523 	index = min(index, List.Count());
    524 	return(List[index]);
    525 }
    526 #endif
    527 
    528 template<class T>
    529 T TListClass<T>::Current_Item(void) const
    530 {
    531 	static T _temp;
    532 	if (List.Count() <= SelectedIndex) {
    533 		return(_temp);
    534 	}
    535 	return(List[SelectedIndex]);
    536 }
    537 
    538 template<class T>
    539 int TListClass<T>::Current_Index(void) const
    540 {
    541 	return(SelectedIndex);
    542 }
    543 
    544 template<class T>
    545 void TListClass<T>::Peer_To_Peer(unsigned flags, KeyNumType &, ControlClass & whom)
    546 {
    547 	if (flags & LEFTRELEASE) {
    548 		if (&whom == &UpGadget) {
    549 			Step(true);
    550 		}
    551 		if (&whom == &DownGadget) {
    552 			Step(false);
    553 		}
    554 	}
    555 
    556 	/*
    557 	**	The slider has changed, so reflect the current list position
    558 	**	according to the slider setting.
    559 	*/
    560 	if (&whom == &ScrollGadget) {
    561 		Set_View_Index(ScrollGadget.Get_Value());
    562 	}
    563 }
    564 
    565 template<class T>
    566 int TListClass<T>::Set_View_Index(int index)
    567 {
    568 	index = Bound(index, 0, List.Count() - LineCount);
    569 	if (index != CurrentTopIndex) {
    570 		CurrentTopIndex = index;
    571 		Flag_To_Redraw();
    572 		if (IsScrollActive) {
    573 			ScrollGadget.Set_Value(CurrentTopIndex);
    574 		}
    575 		return(true);
    576 	}
    577 	return(false);
    578 }
    579 
    580 template<class T>
    581 int TListClass<T>::Add_Scroll_Bar(void)
    582 {
    583 	if (!IsScrollActive) {
    584 		IsScrollActive = true;
    585 
    586 		/*
    587 		**	Everything has been created successfully. Flag the list box to be
    588 		**	redrawn because it now must be made narrower to accomodate the new
    589 		**	slider gadgets.
    590 		*/
    591 		Flag_To_Redraw();
    592 		Width -= ScrollGadget.Width;
    593 
    594 		/*
    595 		**	Tell the newly created gadgets that they should inform this list box
    596 		**	whenever they get touched. In this way, the list box will automatically
    597 		**	be updated under control of the slider buttons.
    598 		*/
    599 		UpGadget.Make_Peer(*this);
    600 		DownGadget.Make_Peer(*this);
    601 		ScrollGadget.Make_Peer(*this);
    602 
    603 		/*
    604 		**	Add these newly created gadgets to the same gadget list that the
    605 		**	list box is part of.
    606 		*/
    607 		UpGadget.Add(*this);
    608 		DownGadget.Add(*this);
    609 		ScrollGadget.Add(*this);
    610 
    611 		/*
    612 		**	Make sure these added gadgets get redrawn at the next opportunity.
    613 		*/
    614 		UpGadget.Flag_To_Redraw();
    615 		DownGadget.Flag_To_Redraw();
    616 		ScrollGadget.Flag_To_Redraw();
    617 
    618 		/*
    619 		**	Inform the slider of the size of the window and the current view position.
    620 		*/
    621 		ScrollGadget.Set_Maximum(List.Count());
    622 		ScrollGadget.Set_Thumb_Size(LineCount);
    623 		ScrollGadget.Set_Value(CurrentTopIndex);
    624 
    625 		/*
    626 		**	Return with success flag.
    627 		*/
    628 		return(true);
    629 	}
    630 	return(false);
    631 }
    632 
    633 template<class T>
    634 int TListClass<T>::Remove_Scroll_Bar(void)
    635 {
    636 	if (IsScrollActive) {
    637 		IsScrollActive = false;
    638 		Width += ScrollGadget.Width;
    639 		ScrollGadget.Remove();
    640 		UpGadget.Remove();
    641 		DownGadget.Remove();
    642 		Flag_To_Redraw();
    643 		return(true);
    644 	}
    645 	return(false);
    646 }
    647 
    648 template<class T>
    649 void TListClass<T>::Set_Tabs(int const * tabs)
    650 {
    651 	Tabs = tabs;
    652 }
    653 
    654 #ifdef NEVER
    655 template<class T>
    656 void TListClass<T>::Draw_Entry(int index, int x, int y, int width, int selected)
    657 {
    658 	if (TextFlags & TPF_6PT_GRAD) {
    659 		TextPrintType flags = TextFlags;
    660 
    661 		if (selected) {
    662 			flags = flags | TPF_BRIGHT_COLOR;
    663 			LogicPage->Fill_Rect(x, y, x + width - 1, y + LineHeight - 1, CC_GREEN_SHADOW);
    664 		} else {
    665 			if (!(flags & TPF_USE_GRAD_PAL)) {
    666 				flags = flags | TPF_MEDIUM_COLOR;
    667 			}
    668 		}
    669 
    670 		Conquer_Clip_Text_Print(List[index], x, y, CC_GREEN, TBLACK, flags, width, Tabs);
    671 
    672 	} else {
    673 		Conquer_Clip_Text_Print(List[index], x, y, (selected ? BLUE : WHITE), TBLACK, TextFlags, width, Tabs);
    674 	}
    675 }
    676 #endif
    677 
    678 template<class T>
    679 LinkClass & TListClass<T>::Add(LinkClass & list)
    680 {
    681 	/*
    682 	**	Add the scroll bar gadgets if they're active.
    683 	*/
    684 	if (IsScrollActive) {
    685 		ScrollGadget.Add(list);
    686 		DownGadget.Add(list);
    687 		UpGadget.Add(list);
    688 	}
    689 
    690 	/*
    691 	**	Add myself to the list, then return.
    692 	*/
    693 	return(ControlClass::Add(list));
    694 }
    695 
    696 template<class T>
    697 LinkClass & TListClass<T>::Add_Head(LinkClass & list)
    698 {
    699 	/*
    700 	**	Add the scroll bar gadgets if they're active.
    701 	*/
    702 	if (IsScrollActive) {
    703 		ScrollGadget.Add_Head(list);
    704 		DownGadget.Add_Head(list);
    705 		UpGadget.Add_Head(list);
    706 	}
    707 
    708 	/*
    709 	**	Add myself to the list, then return.
    710 	*/
    711 	return(ControlClass::Add_Head(list));
    712 }
    713 
    714 template<class T>
    715 LinkClass & TListClass<T>::Add_Tail(LinkClass & list)
    716 {
    717 	/*
    718 	**	Add myself to the list.
    719 	*/
    720 	ControlClass::Add_Tail(list);
    721 
    722 	/*
    723 	**	Add the scroll bar gadgets if they're active.
    724 	*/
    725 	if (IsScrollActive) {
    726 		UpGadget.Add_Tail(list);
    727 		DownGadget.Add_Tail(list);
    728 		ScrollGadget.Add_Tail(list);
    729 	}
    730 
    731 	return(Head_Of_List());
    732 }
    733 
    734 template<class T>
    735 GadgetClass * TListClass<T>::Remove(void)
    736 {
    737 	/*
    738 	**	Remove the scroll bar if it's active
    739 	*/
    740 	if (IsScrollActive) {
    741 		ScrollGadget.Remove();
    742 		DownGadget.Remove();
    743 		UpGadget.Remove();
    744 	}
    745 
    746 	/*
    747 	**	Remove myself & return
    748 	*/
    749 	return(ControlClass::Remove());
    750 }
    751 
    752 template<class T>
    753 void TListClass<T>::Set_Selected_Index(int index)
    754 {
    755    if ((unsigned)index < List.Count()) {
    756 		SelectedIndex = index;
    757 		Flag_To_Redraw();
    758 		if (SelectedIndex < CurrentTopIndex) {
    759 			Set_View_Index(SelectedIndex);
    760 		}
    761 		if (SelectedIndex >= CurrentTopIndex+LineCount) {
    762 			Set_View_Index(SelectedIndex-(LineCount-1));
    763 		}
    764    }
    765 }
    766 
    767 template<class T>
    768 int TListClass<T>::Step_Selected_Index(int step)
    769 {
    770 	int old = SelectedIndex;
    771 
    772 	Set_Selected_Index(old + step);
    773 	return(old);
    774 }
    775 
    776 template<class T>
    777 void TListClass<T>::Flag_To_Redraw(void)
    778 {
    779 	if (IsScrollActive) {
    780 		UpGadget.Flag_To_Redraw();
    781 		DownGadget.Flag_To_Redraw();
    782 		ScrollGadget.Flag_To_Redraw();
    783 	}
    784 	ControlClass::Flag_To_Redraw();
    785 }
    786 
    787 template<class T>
    788 void TListClass<T>::Set_Selected_Index(T text)
    789 {
    790 	for (int index = 0; index < Count(); index++) {
    791 		if (text == Get_Item(index)) {
    792 			Set_Selected_Index(index);
    793 			break;
    794 		}
    795 	}
    796 }
    797 
    798 
    799 #endif