src/news_gui.cpp
changeset 8094 58a8fe00746a
parent 7837 65d7362153a6
child 8320 6ffad7a5d242
child 9722 ebf0ece7d8f6
equal deleted inserted replaced
8093:6f0fa5c9dacc 8094:58a8fe00746a
     1 /* $Id$ */
     1 /* $Id$ */
     2 
     2 
     3 /** @file news_gui.cpp */
       
     4 
     3 
     5 #include "stdafx.h"
     4 #include "stdafx.h"
     6 #include "openttd.h"
     5 #include "openttd.h"
     7 #include "functions.h"
     6 #include "functions.h"
     8 #include "strings.h"
     7 #include "strings.h"
    17 #include "sound.h"
    16 #include "sound.h"
    18 #include "variables.h"
    17 #include "variables.h"
    19 #include "date.h"
    18 #include "date.h"
    20 #include "string.h"
    19 #include "string.h"
    21 
    20 
    22 /* News system
    21 /** @file news_gui.cpp
       
    22  *
    23  * News system is realized as a FIFO queue (in an array)
    23  * News system is realized as a FIFO queue (in an array)
    24  * The positions in the queue can't be rearranged, we only access
    24  * The positions in the queue can't be rearranged, we only access
    25  * the array elements through pointers to the elements. Once the
    25  * the array elements through pointers to the elements. Once the
    26  * array is full, the oldest entry (_oldest_news) is being overwritten
    26  * array is full, the oldest entry (\a _oldest_news) is being overwritten
    27  * by the newest (_latest news).
    27  * by the newest (\a _latest_news).
    28  *
    28  *
       
    29  * \verbatim
    29  * oldest                   current   lastest
    30  * oldest                   current   lastest
    30  *  |                          |         |
    31  *  |                          |         |
    31  * [O------------F-------------C---------L           ]
    32  * [O------------F-------------C---------L           ]
    32  *               |
    33  *               |
    33  *            forced
    34  *            forced
       
    35  * \endverbatim
    34  *
    36  *
    35  * Of course by using an array we can have situations like
    37  * Of course by using an array we can have situations like
    36  *
    38  *
       
    39  * \verbatim
    37  * [----L          O-----F---------C-----------------]
    40  * [----L          O-----F---------C-----------------]
    38  * This is where we have wrapped around the array and have
    41  * This is where we have wrapped around the array and have
    39  * (MAX_NEWS - O) + L news items
    42  * (MAX_NEWS - O) + L news items
       
    43  * \endverbatim
    40  */
    44  */
    41 
    45 
       
    46 /** Number of news items in the FIFO queue */
    42 #define MAX_NEWS 30
    47 #define MAX_NEWS 30
    43 #define NB_WIDG_PER_SETTING 4
    48 #define NB_WIDG_PER_SETTING 4
    44 
    49 
    45 typedef byte NewsID;
    50 typedef byte NewsID;
    46 #define INVALID_NEWS 255
    51 #define INVALID_NEWS 255
    47 
    52 
    48 static NewsItem _news_items[MAX_NEWS];
    53 static NewsItem _news_items[MAX_NEWS];      ///< The news FIFO queue
    49 static NewsID _current_news = INVALID_NEWS; // points to news item that should be shown next
    54 static NewsID _current_news = INVALID_NEWS; ///< points to news item that should be shown next
    50 static NewsID _oldest_news = 0;    // points to first item in fifo queue
    55 static NewsID _oldest_news = 0;             ///< points to first item in fifo queue
    51 static NewsID _latest_news = INVALID_NEWS;  // points to last item in fifo queue
    56 static NewsID _latest_news = INVALID_NEWS;  ///< points to last item in fifo queue
    52 /* if the message being shown was forced by the user, its index is stored in
    57 
    53  * _forced_news. forced_news is INVALID_NEWS otherwise.
    58 /** Forced news item.
    54  * (Users can force messages through history or "last message") */
    59  * Users can force an item by accessing the history or "last message".
       
    60  * If the message being shown was forced by the user, its index is stored in
       
    61  * _forced_news. Otherwise, \a _forced_news variable is INVALID_NEWS. */
    55 static NewsID _forced_news = INVALID_NEWS;
    62 static NewsID _forced_news = INVALID_NEWS;
    56 
    63 
    57 static byte _total_news = 0; // total news count
    64 static byte _total_news = 0; ///< Number of news items in FIFO queue @see _news_items
    58 
    65 
    59 void DrawNewsNewVehicleAvail(Window *w);
    66 void DrawNewsNewVehicleAvail(Window *w);
    60 void DrawNewsBankrupcy(Window *w);
    67 void DrawNewsBankrupcy(Window *w);
    61 static void MoveToNextItem();
    68 static void MoveToNextItem();
    62 
    69 
    63 StringID GetNewsStringNewVehicleAvail(const NewsItem *ni);
    70 StringID GetNewsStringNewVehicleAvail(const NewsItem *ni);
    64 StringID GetNewsStringBankrupcy(const NewsItem *ni);
    71 StringID GetNewsStringBankrupcy(const NewsItem *ni);
    65 
    72 
    66 static DrawNewsCallbackProc * const _draw_news_callback[] = {
    73 static DrawNewsCallbackProc * const _draw_news_callback[] = {
    67 	DrawNewsNewVehicleAvail,  //< DNC_VEHICLEAVAIL
    74 	DrawNewsNewVehicleAvail,  ///< DNC_VEHICLEAVAIL
    68 	DrawNewsBankrupcy,        //< DNC_BANKRUPCY
    75 	DrawNewsBankrupcy,        ///< DNC_BANKRUPCY
    69 };
    76 };
    70 
    77 
    71 extern GetNewsStringCallbackProc * const _get_news_string_callback[];
    78 extern GetNewsStringCallbackProc * const _get_news_string_callback[];
    72 GetNewsStringCallbackProc * const _get_news_string_callback[] = {
    79 GetNewsStringCallbackProc * const _get_news_string_callback[] = {
    73 	GetNewsStringNewVehicleAvail,  ///< DNC_VEHICLEAVAIL
    80 	GetNewsStringNewVehicleAvail,  ///< DNC_VEHICLEAVAIL
    74 	GetNewsStringBankrupcy,        ///< DNC_BANKRUPCY
    81 	GetNewsStringBankrupcy,        ///< DNC_BANKRUPCY
    75 };
    82 };
    76 
    83 
       
    84 /** Initialize the news-items data structures */
    77 void InitNewsItemStructs()
    85 void InitNewsItemStructs()
    78 {
    86 {
    79 	memset(_news_items, 0, sizeof(_news_items));
    87 	memset(_news_items, 0, sizeof(_news_items));
    80 	_current_news = INVALID_NEWS;
    88 	_current_news = INVALID_NEWS;
    81 	_oldest_news = 0;
    89 	_oldest_news = 0;
   217 		SetDirtyBlocks(w->left, w->top - diff, w->left + w->width, w->top + w->height);
   225 		SetDirtyBlocks(w->left, w->top - diff, w->left + w->width, w->top + w->height);
   218 	} break;
   226 	} break;
   219 	}
   227 	}
   220 }
   228 }
   221 
   229 
   222 /** Return the correct index in the pseudo-fifo
   230 /**
   223  * queue and deals with overflows when increasing the index */
   231  * Return the correct index in the pseudo-fifo
       
   232  * queue and deals with overflows when increasing the index
       
   233  */
   224 static inline NewsID increaseIndex(NewsID i)
   234 static inline NewsID increaseIndex(NewsID i)
   225 {
   235 {
   226 	assert(i != INVALID_NEWS);
   236 	assert(i != INVALID_NEWS);
   227 	return (i + 1) % MAX_NEWS;
   237 	return (i + 1) % MAX_NEWS;
   228 }
   238 }
   229 
   239 
   230 /** Return the correct index in the pseudo-fifo
   240 /**
   231  * queue and deals with overflows when decreasing the index */
   241  * Return the correct index in the pseudo-fifo
       
   242  * queue and deals with overflows when decreasing the index
       
   243  */
   232 static inline NewsID decreaseIndex(NewsID i)
   244 static inline NewsID decreaseIndex(NewsID i)
   233 {
   245 {
   234 	assert(i != INVALID_NEWS);
   246 	assert(i != INVALID_NEWS);
   235 	return (i + MAX_NEWS - 1) % MAX_NEWS;
   247 	return (i + MAX_NEWS - 1) % MAX_NEWS;
   236 }
   248 }
   237 
   249 
   238 /** Add a new newsitem to be shown.
   250 /**
   239  * @param string String to display, can have special values based on parameter 'flags'
   251  * Add a new newsitem to be shown.
       
   252  * @param string String to display, can have special values based on parameter \a flags
   240  * @param flags various control bits that will show various news-types. See macro NEWS_FLAGS()
   253  * @param flags various control bits that will show various news-types. See macro NEWS_FLAGS()
   241  * @param data_a news-specific value based on news type
   254  * @param data_a news-specific value based on news type
   242  * @param data_b news-specific value based on news type
   255  * @param data_b news-specific value based on news type
   243  * @note flags exists of 4 byte-sized extra parameters.
   256  * @note flags exists of 4 byte-sized extra parameters.
   244  * 1.  0 -  7 display_mode, any of the NewsMode enums (NM_)
   257  *  -# Bits  0 -  7 display_mode, any of the NewsMode enums (NM_)
   245  * 2.  8 - 15 news flags, any of the NewsFlags enums (NF_) NF_INCOLOR are set automatically if needed
   258  *  -# Bits  8 - 15 news flags, any of the NewsFlags enums (NF_)
   246  * 3. 16 - 23 news category, any of the NewsType enums (NT_)
   259  *  -# Bits 16 - 23 news category, any of the NewsType enums (NT_)
   247  * 4. 24 - 31 news callback function, any of the NewsCallback enums (DNC_)
   260  *  -# Bits 24 - 31 news callback function, any of the NewsCallback enums (DNC_)
   248  * If the display mode is NM_CALLBACK special news is shown and parameter
   261  *
   249  * stringid has a special meaning.
   262  * If the display mode is NM_CALLBACK, special news is shown and parameter
   250  * DNC_TRAINAVAIL, DNC_ROADAVAIL, DNC_SHIPAVAIL, DNC_AIRCRAFTAVAIL: StringID is
   263  * \a string has a special meaning.
   251  * the index of the engine that is shown
   264  *  - For DNC_TRAINAVAIL, DNC_ROADAVAIL, DNC_SHIPAVAIL, DNC_AIRCRAFTAVAIL messages: StringID is
   252  * DNC_BANKRUPCY: bytes 0-3 of StringID contains the player that is in trouble,
   265  *    the index of the engine that is shown
   253  * and 4-7 contains what kind of bankrupcy message is shown, NewsBankrupcy enum (NB_)
   266  *
       
   267  *  - For DNC_BANKRUPCY: bytes 0-3 of StringID contains the player that is in trouble,
       
   268  *    and 4-7 contains what kind of bankrupcy message is shown.
       
   269  *    @see NewsBankrupcy
       
   270  *
   254  * @see NewsMode
   271  * @see NewsMode
   255  * @see NewsFlags
   272  * @see NewsFlags
   256  * @see NewsType
   273  * @see NewsType
   257  * @see NewsCallback */
   274  * @see NewsCallback
       
   275  */
   258 void AddNewsItem(StringID string, uint32 flags, uint data_a, uint data_b)
   276 void AddNewsItem(StringID string, uint32 flags, uint data_a, uint data_b)
   259 {
   277 {
   260 	NewsID l_news;
   278 	NewsID l_news;
   261 
   279 
   262 	if (_game_mode == GM_MENU) return;
   280 	if (_game_mode == GM_MENU) return;
   308 		w->vscroll.count = _total_news;
   326 		w->vscroll.count = _total_news;
   309 	}
   327 	}
   310 }
   328 }
   311 
   329 
   312 
   330 
   313 /* Don't show item if it's older than x days, corresponds with NewsType in news.h */
   331 /**
   314 static const byte _news_items_age[] = {60, 60, 90, 60, 90, 30, 150, 30, 90, 180};
   332  * Maximum age of news items.
       
   333  * Don't show item if it's older than x days, corresponds with NewsType in news.h
       
   334  * @see NewsType
       
   335  */
       
   336 static const byte _news_items_age[NT_END] = {
       
   337 	60,  ///< NT_ARRIVAL_PLAYER
       
   338 	60,  ///< NT_ARRIVAL_OTHER
       
   339 	90,  ///< NT_ACCIDENT
       
   340 	60,  ///< NT_COMPANY_INFO
       
   341 	90,  ///< NT_OPENCLOSE
       
   342 	30,  ///< NT_ECONOMY
       
   343 	150, ///< NT_ADVICE
       
   344 	30,  ///< NT_NEW_VEHICLES
       
   345 	90,  ///< NT_ACCEPTANCE
       
   346 	180, ///< NT_SUBSIDIES
       
   347 	60   ///< NT_GENERAL
       
   348 };
       
   349 
   315 
   350 
   316 static const Widget _news_type13_widgets[] = {
   351 static const Widget _news_type13_widgets[] = {
   317 {      WWT_PANEL,   RESIZE_NONE,    15,     0,   429,     0,   169, 0x0, STR_NULL},
   352 {      WWT_PANEL,   RESIZE_NONE,    15,     0,   429,     0,   169, 0x0, STR_NULL},
   318 {      WWT_PANEL,   RESIZE_NONE,    15,     0,    10,     0,    11, 0x0, STR_NULL},
   353 {      WWT_PANEL,   RESIZE_NONE,    15,     0,    10,     0,    11, 0x0, STR_NULL},
   319 {   WIDGETS_END},
   354 {   WIDGETS_END},
   383 	"acceptance",
   418 	"acceptance",
   384 	"subsidies",
   419 	"subsidies",
   385 	"general",
   420 	"general",
   386 };
   421 };
   387 
   422 
   388 /** Get the value of an item of the news-display settings. This is
   423 /**
       
   424  * Get the value of an item of the news-display settings. This is
   389  * a little tricky since on/off/summary must use 2 bits to store the value
   425  * a little tricky since on/off/summary must use 2 bits to store the value
   390  * @param item the item whose value is requested
   426  * @param item the item whose value is requested
   391  * @return return the found value which is between 0-2
   427  * @return return the found value which is between 0-2
   392  */
   428  */
   393 static inline byte GetNewsDisplayValue(byte item)
   429 static inline byte GetNewsDisplayValue(byte item)
   394 {
   430 {
   395 	assert(item < NT_END && GB(_news_display_opt, item * 2, 2) <= 2);
   431 	assert(item < NT_END && GB(_news_display_opt, item * 2, 2) <= 2);
   396 	return GB(_news_display_opt, item * 2, 2);
   432 	return GB(_news_display_opt, item * 2, 2);
   397 }
   433 }
   398 
   434 
   399 /** Set the value of an item in the news-display settings. This is
   435 /**
       
   436  * Set the value of an item in the news-display settings. This is
   400  * a little tricky since on/off/summary must use 2 bits to store the value
   437  * a little tricky since on/off/summary must use 2 bits to store the value
   401  * @param item the item whose value is being set
   438  * @param item the item whose value is being set
   402  * @param val new value
   439  * @param val new value
   403  */
   440  */
   404 static inline void SetNewsDisplayValue(byte item, byte val)
   441 static inline void SetNewsDisplayValue(byte item, byte val)
   405 {
   442 {
   406 	assert(item < NT_END && val <= 2);
   443 	assert(item < NT_END && val <= 2);
   407 	SB(_news_display_opt, item * 2, 2, val);
   444 	SB(_news_display_opt, item * 2, 2, val);
   408 }
   445 }
   409 
   446 
   410 /* open up an own newspaper window for the news item */
   447 /** Open up an own newspaper window for the news item */
   411 static void ShowNewspaper(NewsItem *ni)
   448 static void ShowNewspaper(NewsItem *ni)
   412 {
   449 {
   413 	Window *w;
   450 	Window *w;
   414 	SoundFx sound;
   451 	SoundFx sound;
   415 	int top;
   452 	int top;
   455 
   492 
   456 	WP(w, news_d).ni = &_news_items[_forced_news == INVALID_NEWS ? _current_news : _forced_news];
   493 	WP(w, news_d).ni = &_news_items[_forced_news == INVALID_NEWS ? _current_news : _forced_news];
   457 	w->flags4 |= WF_DISABLE_VP_SCROLL;
   494 	w->flags4 |= WF_DISABLE_VP_SCROLL;
   458 }
   495 }
   459 
   496 
   460 /* show news item in the ticker */
   497 /** Show news item in the ticker */
   461 static void ShowTicker(const NewsItem *ni)
   498 static void ShowTicker(const NewsItem *ni)
   462 {
   499 {
   463 	Window *w;
   500 	Window *w;
   464 
   501 
   465 	if (_news_ticker_sound) SndPlayFx(SND_16_MORSE);
   502 	if (_news_ticker_sound) SndPlayFx(SND_16_MORSE);
   468 	w = FindWindowById(WC_STATUS_BAR, 0);
   505 	w = FindWindowById(WC_STATUS_BAR, 0);
   469 	if (w != NULL) WP(w, def_d).data_1 = 360;
   506 	if (w != NULL) WP(w, def_d).data_1 = 360;
   470 }
   507 }
   471 
   508 
   472 
   509 
   473 /** Are we ready to show another news item?
   510 /**
   474  * Only if nothing is in the newsticker and no newspaper is displayed */
   511  * Are we ready to show another news item?
       
   512  * Only if nothing is in the newsticker and no newspaper is displayed
       
   513  */
   475 static bool ReadyForNextItem()
   514 static bool ReadyForNextItem()
   476 {
   515 {
   477 	const Window *w;
   516 	const Window *w;
   478 	NewsID item = (_forced_news == INVALID_NEWS) ? _current_news : _forced_news;
   517 	NewsID item = (_forced_news == INVALID_NEWS) ? _current_news : _forced_news;
   479 	NewsItem *ni;
   518 	NewsItem *ni;
   491 
   530 
   492 	/* neither newsticker nor newspaper are running */
   531 	/* neither newsticker nor newspaper are running */
   493 	return (ni->duration == 0 || FindWindowById(WC_NEWS_WINDOW, 0) == NULL);
   532 	return (ni->duration == 0 || FindWindowById(WC_NEWS_WINDOW, 0) == NULL);
   494 }
   533 }
   495 
   534 
       
   535 /** Move to the next news item */
   496 static void MoveToNextItem()
   536 static void MoveToNextItem()
   497 {
   537 {
   498 	DeleteWindowById(WC_NEWS_WINDOW, 0);
   538 	DeleteWindowById(WC_NEWS_WINDOW, 0);
   499 	_forced_news = INVALID_NEWS;
   539 	_forced_news = INVALID_NEWS;
   500 
   540 
   507 
   547 
   508 		/* check the date, don't show too old items */
   548 		/* check the date, don't show too old items */
   509 		if (_date - _news_items_age[ni->type] > ni->date) return;
   549 		if (_date - _news_items_age[ni->type] > ni->date) return;
   510 
   550 
   511 		switch (GetNewsDisplayValue(ni->type)) {
   551 		switch (GetNewsDisplayValue(ni->type)) {
   512 		case 0: { // Off - show nothing only a small reminder in the status bar
   552 			default: NOT_REACHED();
   513 			Window *w = FindWindowById(WC_STATUS_BAR, 0);
   553 			case 0: { // Off - show nothing only a small reminder in the status bar
   514 
   554 				Window *w = FindWindowById(WC_STATUS_BAR, 0);
   515 			if (w != NULL) {
   555 
   516 				WP(w, def_d).data_2 = 91;
   556 				if (w != NULL) {
   517 				SetWindowDirty(w);
   557 					WP(w, def_d).data_2 = 91;
   518 			}
   558 					SetWindowDirty(w);
   519 			break;
   559 				}
   520 		}
       
   521 
       
   522 		case 1: // Summary - show ticker, but if forced big, cascade to full
       
   523 			if (!(ni->flags & NF_FORCE_BIG)) {
       
   524 				ShowTicker(ni);
       
   525 				break;
   560 				break;
   526 			}
   561 			}
   527 			/* Fallthrough */
   562 
   528 
   563 			case 1: // Summary - show ticker, but if forced big, cascade to full
   529 		case 2: // Full - show newspaper
   564 				if (!(ni->flags & NF_FORCE_BIG)) {
   530 			ShowNewspaper(ni);
   565 					ShowTicker(ni);
   531 			break;
   566 					break;
       
   567 				}
       
   568 				/* Fallthrough */
       
   569 
       
   570 			case 2: // Full - show newspaper
       
   571 				ShowNewspaper(ni);
       
   572 				break;
   532 		}
   573 		}
   533 	}
   574 	}
   534 }
   575 }
   535 
   576 
   536 void NewsLoop()
   577 void NewsLoop()
   539 	if (_total_news == 0) return;
   580 	if (_total_news == 0) return;
   540 
   581 
   541 	if (ReadyForNextItem()) MoveToNextItem();
   582 	if (ReadyForNextItem()) MoveToNextItem();
   542 }
   583 }
   543 
   584 
   544 /* Do a forced show of a specific message */
   585 /** Do a forced show of a specific message */
   545 static void ShowNewsMessage(NewsID i)
   586 static void ShowNewsMessage(NewsID i)
   546 {
   587 {
   547 	if (_total_news == 0) return;
   588 	if (_total_news == 0) return;
   548 
   589 
   549 	/* Delete the news window */
   590 	/* Delete the news window */
   559 		DeleteWindowById(WC_NEWS_WINDOW, 0);
   600 		DeleteWindowById(WC_NEWS_WINDOW, 0);
   560 		ShowNewspaper(ni);
   601 		ShowNewspaper(ni);
   561 	}
   602 	}
   562 }
   603 }
   563 
   604 
       
   605 /** Show previous news item */
   564 void ShowLastNewsMessage()
   606 void ShowLastNewsMessage()
   565 {
   607 {
   566 	if (_forced_news == INVALID_NEWS) {
   608 	if (_forced_news == INVALID_NEWS) {
   567 		/* Not forced any news yet, show the current one, unless a news window is
   609 		/* Not forced any news yet, show the current one, unless a news window is
   568 		 * open (which can only be the current one), then show the previous item */
   610 		 * open (which can only be the current one), then show the previous item */
   592 
   634 
   593 	i %= MAX_NEWS;
   635 	i %= MAX_NEWS;
   594 	return i;
   636 	return i;
   595 }
   637 }
   596 
   638 
   597 /** Draw an unformatted news message truncated to a maximum length. If
   639 /**
       
   640  * Draw an unformatted news message truncated to a maximum length. If
   598  * length exceeds maximum length it will be postfixed by '...'
   641  * length exceeds maximum length it will be postfixed by '...'
   599  * @param x,y position of the string
   642  * @param x,y position of the string
   600  * @param color the color the string will be shown in
   643  * @param color the color the string will be shown in
   601  * @param *ni NewsItem being printed
   644  * @param *ni NewsItem being printed
   602  * @param maxw maximum width of string in pixels
   645  * @param maxw maximum width of string in pixels
   705 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   748 	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
   706 	_message_history_widgets,
   749 	_message_history_widgets,
   707 	MessageHistoryWndProc
   750 	MessageHistoryWndProc
   708 };
   751 };
   709 
   752 
       
   753 /** Display window with news messages history */
   710 void ShowMessageHistory()
   754 void ShowMessageHistory()
   711 {
   755 {
   712 	Window *w;
   756 	Window *w;
   713 
   757 
   714 	DeleteWindowById(WC_MESSAGE_HISTORY, 0);
   758 	DeleteWindowById(WC_MESSAGE_HISTORY, 0);
   731 	WIDGET_NEWSOPT_DROP_SUMMARY,      ///< Drop down button for same upper button
   775 	WIDGET_NEWSOPT_DROP_SUMMARY,      ///< Drop down button for same upper button
   732 	WIDGET_NEWSOPT_SOUNDTICKER  = 7,  ///< Button activating sound on events
   776 	WIDGET_NEWSOPT_SOUNDTICKER  = 7,  ///< Button activating sound on events
   733 	WIDGET_NEWSOPT_START_OPTION = 9,  ///< First widget that is part of a group [<] .. [.]
   777 	WIDGET_NEWSOPT_START_OPTION = 9,  ///< First widget that is part of a group [<] .. [.]
   734 };
   778 };
   735 
   779 
   736 /** Setup the disabled/enabled buttons in the message window
   780 /**
       
   781  * Setup the disabled/enabled buttons in the message window
   737  * If the value is 'off' disable the [<] widget, and enable the [>] one
   782  * If the value is 'off' disable the [<] widget, and enable the [>] one
   738  * Same-wise for all the others. Starting value of 4 is the first widget
   783  * Same-wise for all the others. Starting value of 4 is the first widget
   739  * group. These are grouped as [<][>] .. [<][>], etc.
   784  * group. These are grouped as [<][>] .. [<][>], etc.
   740  * @param w Window been used
   785  * @param w Window been used
   741  * @param value to set in the widget
   786  * @param value to set in the widget