src/widget.cpp
branchNewGRF_ports
changeset 6871 5a9dc001e1ad
parent 6719 4cc327ad39d5
child 6872 1c4a4a609f85
equal deleted inserted replaced
6870:ca3fd1fbe311 6871:5a9dc001e1ad
   138 	for (index = 0; index < w->widget_count; index++) {
   138 	for (index = 0; index < w->widget_count; index++) {
   139 		const Widget *wi = &w->widget[index];
   139 		const Widget *wi = &w->widget[index];
   140 		if (wi->type == WWT_EMPTY || wi->type == WWT_FRAME) continue;
   140 		if (wi->type == WWT_EMPTY || wi->type == WWT_FRAME) continue;
   141 
   141 
   142 		if (x >= wi->left && x <= wi->right && y >= wi->top &&  y <= wi->bottom &&
   142 		if (x >= wi->left && x <= wi->right && y >= wi->top &&  y <= wi->bottom &&
   143 				!IsWindowWidgetHidden(w, index)) {
   143 				!w->IsWidgetHidden(index)) {
   144 			found_index = index;
   144 			found_index = index;
   145 		}
   145 		}
   146 	}
   146 	}
   147 
   147 
   148 	return found_index;
   148 	return found_index;
   182 
   182 
   183 
   183 
   184 void DrawWindowWidgets(const Window *w)
   184 void DrawWindowWidgets(const Window *w)
   185 {
   185 {
   186 	const DrawPixelInfo* dpi = _cur_dpi;
   186 	const DrawPixelInfo* dpi = _cur_dpi;
   187 	Rect r;
   187 
   188 	uint i;
   188 	for (uint i = 0; i < w->widget_count; i++) {
   189 
       
   190 	for (i = 0; i < w->widget_count; i++) {
       
   191 		const Widget *wi = &w->widget[i];
   189 		const Widget *wi = &w->widget[i];
   192 		bool clicked = IsWindowWidgetLowered(w, i);
   190 		bool clicked = w->IsWidgetLowered(i);
   193 
   191 		Rect r;
   194 		if (dpi->left > (r.right=/*w->left + */wi->right) ||
   192 
   195 				dpi->left + dpi->width <= (r.left=wi->left/* + w->left*/) ||
   193 		if (dpi->left > (r.right = wi->right) ||
   196 				dpi->top > (r.bottom=/*w->top +*/ wi->bottom) ||
   194 				dpi->left + dpi->width <= (r.left = wi->left) ||
   197 				dpi->top + dpi->height <= (r.top = /*w->top +*/ wi->top) ||
   195 				dpi->top > (r.bottom = wi->bottom) ||
   198 				IsWindowWidgetHidden(w, i)) {
   196 				dpi->top + dpi->height <= (r.top = wi->top) ||
       
   197 				w->IsWidgetHidden(i)) {
   199 			continue;
   198 			continue;
   200 		}
   199 		}
   201 
   200 
   202 		switch (wi->type & WWT_MASK) {
   201 		switch (wi->type & WWT_MASK) {
   203 		case WWT_IMGBTN:
   202 		case WWT_IMGBTN:
   204 		case WWT_IMGBTN_2: {
   203 		case WWT_IMGBTN_2: {
   205 			int img = wi->data;
   204 			SpriteID img = wi->data;
   206 			assert(img != 0);
   205 			assert(img != 0);
   207 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   206 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   208 
   207 
   209 			/* show different image when clicked for WWT_IMGBTN_2 */
   208 			/* show different image when clicked for WWT_IMGBTN_2 */
   210 			if ((wi->type & WWT_MASK) == WWT_IMGBTN_2 && clicked) img++;
   209 			if ((wi->type & WWT_MASK) == WWT_IMGBTN_2 && clicked) img++;
   227 		case WWT_LABEL: {
   226 		case WWT_LABEL: {
   228 			StringID str = wi->data;
   227 			StringID str = wi->data;
   229 
   228 
   230 			if ((wi->type & WWT_MASK) == WWT_TEXTBTN_2 && clicked) str++;
   229 			if ((wi->type & WWT_MASK) == WWT_TEXTBTN_2 && clicked) str++;
   231 
   230 
   232 			DrawStringCentered(((r.left + r.right + 1) >> 1) + clicked, ((r.top + r.bottom + 1) >> 1) - 5 + clicked, str, 0);
   231 			DrawStringCentered(((r.left + r.right + 1) >> 1) + clicked, ((r.top + r.bottom + 1) >> 1) - 5 + clicked, str, TC_FROMSTRING);
   233 			goto draw_default;
   232 			goto draw_default;
   234 		}
   233 		}
   235 
   234 
   236 		case WWT_TEXT: {
   235 		case WWT_TEXT: {
   237 			StringID str = wi->data;
   236 			const StringID str = wi->data;
   238 
   237 
   239 			if (str != STR_NULL) DrawStringTruncated(r.left, r.top, str, wi->color, r.right - r.left);
   238 			if (str != STR_NULL) DrawStringTruncated(r.left, r.top, str, wi->color, r.right - r.left);
   240 			break;
   239 			break;
   241 		}
   240 		}
   242 
   241 
   243 		case WWT_INSET: {
   242 		case WWT_INSET: {
   244 			StringID str = wi->data;
   243 			const StringID str = wi->data;
   245 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, FR_LOWERED | FR_DARKENED);
   244 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, FR_LOWERED | FR_DARKENED);
   246 
   245 
   247 			if (str != STR_NULL) DrawStringTruncated(r.left + 2, r.top + 1, str, 0, r.right - r.left - 10);
   246 			if (str != STR_NULL) DrawStringTruncated(r.left + 2, r.top + 1, str, TC_FROMSTRING, r.right - r.left - 10);
   248 			goto draw_default;
   247 			goto draw_default;
   249 		}
   248 		}
   250 
   249 
   251 		case WWT_MATRIX: {
   250 		case WWT_MATRIX: {
   252 			int c, d, ctr;
   251 			int c, d, ctr;
   273 			for (ctr = d; ctr > 1; ctr--) {
   272 			for (ctr = d; ctr > 1; ctr--) {
   274 				x += amt2;
   273 				x += amt2;
   275 				GfxFillRect(r.left + 1, x, r.right - 1, x, color);
   274 				GfxFillRect(r.left + 1, x, r.right - 1, x, color);
   276 			}
   275 			}
   277 
   276 
   278 			color = _colour_gradient[wi->color&0xF][4];
   277 			color = _colour_gradient[wi->color & 0xF][4];
   279 
   278 
   280 			x = r.left - 1;
   279 			x = r.left - 1;
   281 			for (ctr = c; ctr > 1; ctr--) {
   280 			for (ctr = c; ctr > 1; ctr--) {
   282 				x += amt1;
   281 				x += amt1;
   283 				GfxFillRect(x, r.top + 1, x, r.bottom - 1, color);
   282 				GfxFillRect(x, r.top + 1, x, r.bottom - 1, color);
   284 			}
   283 			}
   285 
   284 
   286 			x = r.top - 1;
   285 			x = r.top - 1;
   287 			for (ctr = d; ctr > 1; ctr--) {
   286 			for (ctr = d; ctr > 1; ctr--) {
   288 				x += amt2;
   287 				x += amt2;
   289 				GfxFillRect(r.left+1, x, r.right-1, x, color);
   288 				GfxFillRect(r.left + 1, x, r.right - 1, x, color);
   290 			}
   289 			}
   291 
   290 
   292 			goto draw_default;
   291 			goto draw_default;
   293 		}
   292 		}
   294 
   293 
   295 		/* vertical scrollbar */
   294 		/* vertical scrollbar */
   296 		case WWT_SCROLLBAR: {
   295 		case WWT_SCROLLBAR: {
   297 			Point pt;
   296 			Point pt;
   298 			int c1,c2;
   297 			int c1, c2;
   299 
   298 
       
   299 			assert(wi->data == 0);
   300 			assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere!
   300 			assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere!
   301 
   301 
   302 			/* draw up/down buttons */
   302 			/* draw up/down buttons */
   303 			clicked = ((w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_UP);
   303 			clicked = ((w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_UP);
   304 			DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   304 			DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   305 			DoDrawString(UPARROW, r.left + 2 + clicked, r.top + clicked, 0x10);
   305 			DoDrawString(UPARROW, r.left + 2 + clicked, r.top + clicked, TC_BLACK);
   306 
   306 
   307 			clicked = (((w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_DOWN));
   307 			clicked = (((w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_DOWN));
   308 			DrawFrameRect(r.left, r.bottom - 9, r.right, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   308 			DrawFrameRect(r.left, r.bottom - 9, r.right, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   309 			DoDrawString(DOWNARROW, r.left + 2 + clicked, r.bottom - 9 + clicked, 0x10);
   309 			DoDrawString(DOWNARROW, r.left + 2 + clicked, r.bottom - 9 + clicked, TC_BLACK);
   310 
   310 
   311 			c1 = _colour_gradient[wi->color&0xF][3];
   311 			c1 = _colour_gradient[wi->color & 0xF][3];
   312 			c2 = _colour_gradient[wi->color&0xF][7];
   312 			c2 = _colour_gradient[wi->color & 0xF][7];
   313 
   313 
   314 			/* draw "shaded" background */
   314 			/* draw "shaded" background */
   315 			GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c2);
   315 			GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c2);
   316 			GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c1 | (1 << PALETTE_MODIFIER_GREYOUT));
   316 			GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c1 | (1 << PALETTE_MODIFIER_GREYOUT));
   317 
   317 
   318 			/* draw shaded lines */
   318 			/* draw shaded lines */
   319 			GfxFillRect(r.left+2, r.top+10, r.left+2, r.bottom-10, c1);
   319 			GfxFillRect(r.left + 2, r.top + 10, r.left + 2, r.bottom - 10, c1);
   320 			GfxFillRect(r.left+3, r.top+10, r.left+3, r.bottom-10, c2);
   320 			GfxFillRect(r.left + 3, r.top + 10, r.left + 3, r.bottom - 10, c2);
   321 			GfxFillRect(r.left+7, r.top+10, r.left+7, r.bottom-10, c1);
   321 			GfxFillRect(r.left + 7, r.top + 10, r.left + 7, r.bottom - 10, c1);
   322 			GfxFillRect(r.left+8, r.top+10, r.left+8, r.bottom-10, c2);
   322 			GfxFillRect(r.left + 8, r.top + 10, r.left + 8, r.bottom - 10, c2);
   323 
   323 
   324 			pt = HandleScrollbarHittest(&w->vscroll, r.top, r.bottom);
   324 			pt = HandleScrollbarHittest(&w->vscroll, r.top, r.bottom);
   325 			DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_MIDDLE ? FR_LOWERED : FR_NONE);
   325 			DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == WF_SCROLL_MIDDLE ? FR_LOWERED : FR_NONE);
   326 			break;
   326 			break;
   327 		}
   327 		}
   328 		case WWT_SCROLL2BAR: {
   328 		case WWT_SCROLL2BAR: {
   329 			Point pt;
   329 			Point pt;
   330 			int c1,c2;
   330 			int c1, c2;
   331 
   331 
       
   332 			assert(wi->data == 0);
   332 			assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere!
   333 			assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere!
   333 
   334 
   334 			/* draw up/down buttons */
   335 			/* draw up/down buttons */
   335 			clicked = ((w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_UP | WF_SCROLL2));
   336 			clicked = ((w->flags4 & (WF_SCROLL_UP | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_UP | WF_SCROLL2));
   336 			DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->color,  (clicked) ? FR_LOWERED : FR_NONE);
   337 			DrawFrameRect(r.left, r.top, r.right, r.top + 9, wi->color,  (clicked) ? FR_LOWERED : FR_NONE);
   337 			DoDrawString(UPARROW, r.left + 2 + clicked, r.top + clicked, 0x10);
   338 			DoDrawString(UPARROW, r.left + 2 + clicked, r.top + clicked, TC_BLACK);
   338 
   339 
   339 			clicked = ((w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_DOWN | WF_SCROLL2));
   340 			clicked = ((w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_DOWN | WF_SCROLL2));
   340 			DrawFrameRect(r.left, r.bottom - 9, r.right, r.bottom, wi->color,  (clicked) ? FR_LOWERED : FR_NONE);
   341 			DrawFrameRect(r.left, r.bottom - 9, r.right, r.bottom, wi->color,  (clicked) ? FR_LOWERED : FR_NONE);
   341 			DoDrawString(DOWNARROW, r.left + 2 + clicked, r.bottom - 9 + clicked, 0x10);
   342 			DoDrawString(DOWNARROW, r.left + 2 + clicked, r.bottom - 9 + clicked, TC_BLACK);
   342 
   343 
   343 			c1 = _colour_gradient[wi->color&0xF][3];
   344 			c1 = _colour_gradient[wi->color & 0xF][3];
   344 			c2 = _colour_gradient[wi->color&0xF][7];
   345 			c2 = _colour_gradient[wi->color & 0xF][7];
   345 
   346 
   346 			/* draw "shaded" background */
   347 			/* draw "shaded" background */
   347 			GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c2);
   348 			GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c2);
   348 			GfxFillRect(r.left, r.top+10, r.right, r.bottom-10, c1 | (1 << PALETTE_MODIFIER_GREYOUT));
   349 			GfxFillRect(r.left, r.top + 10, r.right, r.bottom - 10, c1 | (1 << PALETTE_MODIFIER_GREYOUT));
   349 
   350 
   350 			/* draw shaded lines */
   351 			/* draw shaded lines */
   351 			GfxFillRect(r.left+2, r.top+10, r.left+2, r.bottom-10, c1);
   352 			GfxFillRect(r.left + 2, r.top + 10, r.left + 2, r.bottom - 10, c1);
   352 			GfxFillRect(r.left+3, r.top+10, r.left+3, r.bottom-10, c2);
   353 			GfxFillRect(r.left + 3, r.top + 10, r.left + 3, r.bottom - 10, c2);
   353 			GfxFillRect(r.left+7, r.top+10, r.left+7, r.bottom-10, c1);
   354 			GfxFillRect(r.left + 7, r.top + 10, r.left + 7, r.bottom - 10, c1);
   354 			GfxFillRect(r.left+8, r.top+10, r.left+8, r.bottom-10, c2);
   355 			GfxFillRect(r.left + 8, r.top + 10, r.left + 8, r.bottom - 10, c2);
   355 
   356 
   356 			pt = HandleScrollbarHittest(&w->vscroll2, r.top, r.bottom);
   357 			pt = HandleScrollbarHittest(&w->vscroll2, r.top, r.bottom);
   357 			DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_MIDDLE | WF_SCROLL2) ? FR_LOWERED : FR_NONE);
   358 			DrawFrameRect(r.left, pt.x, r.right, pt.y, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL | WF_SCROLL2)) == (WF_SCROLL_MIDDLE | WF_SCROLL2) ? FR_LOWERED : FR_NONE);
   358 			break;
   359 			break;
   359 		}
   360 		}
   360 
   361 
   361 		/* horizontal scrollbar */
   362 		/* horizontal scrollbar */
   362 		case WWT_HSCROLLBAR: {
   363 		case WWT_HSCROLLBAR: {
   363 			Point pt;
   364 			Point pt;
   364 			int c1,c2;
   365 			int c1, c2;
   365 
   366 
       
   367 			assert(wi->data == 0);
   366 			assert(r.bottom - r.top == 11); // XXX - to ensure the same sizes are used everywhere!
   368 			assert(r.bottom - r.top == 11); // XXX - to ensure the same sizes are used everywhere!
   367 
   369 
   368 			clicked = ((w->flags4 & (WF_SCROLL_UP | WF_HSCROLL)) == (WF_SCROLL_UP | WF_HSCROLL));
   370 			clicked = ((w->flags4 & (WF_SCROLL_UP | WF_HSCROLL)) == (WF_SCROLL_UP | WF_HSCROLL));
   369 			DrawFrameRect(r.left, r.top, r.left + 9, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   371 			DrawFrameRect(r.left, r.top, r.left + 9, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   370 			DrawSprite(SPR_ARROW_LEFT, PAL_NONE, r.left + 1 + clicked, r.top + 1 + clicked);
   372 			DrawSprite(SPR_ARROW_LEFT, PAL_NONE, r.left + 1 + clicked, r.top + 1 + clicked);
   371 
   373 
   372 			clicked = ((w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL)) == (WF_SCROLL_DOWN | WF_HSCROLL));
   374 			clicked = ((w->flags4 & (WF_SCROLL_DOWN | WF_HSCROLL)) == (WF_SCROLL_DOWN | WF_HSCROLL));
   373 			DrawFrameRect(r.right-9, r.top, r.right, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   375 			DrawFrameRect(r.right - 9, r.top, r.right, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   374 			DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - 8 + clicked, r.top + 1 + clicked);
   376 			DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, r.right - 8 + clicked, r.top + 1 + clicked);
   375 
   377 
   376 			c1 = _colour_gradient[wi->color&0xF][3];
   378 			c1 = _colour_gradient[wi->color & 0xF][3];
   377 			c2 = _colour_gradient[wi->color&0xF][7];
   379 			c2 = _colour_gradient[wi->color & 0xF][7];
   378 
   380 
   379 			/* draw "shaded" background */
   381 			/* draw "shaded" background */
   380 			GfxFillRect(r.left+10, r.top, r.right-10, r.bottom, c2);
   382 			GfxFillRect(r.left + 10, r.top, r.right - 10, r.bottom, c2);
   381 			GfxFillRect(r.left+10, r.top, r.right-10, r.bottom, c1 | (1 << PALETTE_MODIFIER_GREYOUT));
   383 			GfxFillRect(r.left + 10, r.top, r.right - 10, r.bottom, c1 | (1 << PALETTE_MODIFIER_GREYOUT));
   382 
   384 
   383 			/* draw shaded lines */
   385 			/* draw shaded lines */
   384 			GfxFillRect(r.left+10, r.top+2, r.right-10, r.top+2, c1);
   386 			GfxFillRect(r.left + 10, r.top + 2, r.right - 10, r.top + 2, c1);
   385 			GfxFillRect(r.left+10, r.top+3, r.right-10, r.top+3, c2);
   387 			GfxFillRect(r.left + 10, r.top + 3, r.right - 10, r.top + 3, c2);
   386 			GfxFillRect(r.left+10, r.top+7, r.right-10, r.top+7, c1);
   388 			GfxFillRect(r.left + 10, r.top + 7, r.right - 10, r.top + 7, c1);
   387 			GfxFillRect(r.left+10, r.top+8, r.right-10, r.top+8, c2);
   389 			GfxFillRect(r.left + 10, r.top + 8, r.right - 10, r.top + 8, c2);
   388 
   390 
   389 			/* draw actual scrollbar */
   391 			/* draw actual scrollbar */
   390 			pt = HandleScrollbarHittest(&w->hscroll, r.left, r.right);
   392 			pt = HandleScrollbarHittest(&w->hscroll, r.left, r.right);
   391 			DrawFrameRect(pt.x, r.top, pt.y, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL)) == (WF_SCROLL_MIDDLE | WF_HSCROLL) ? FR_LOWERED : FR_NONE);
   393 			DrawFrameRect(pt.x, r.top, pt.y, r.bottom, wi->color, (w->flags4 & (WF_SCROLL_MIDDLE | WF_HSCROLL)) == (WF_SCROLL_MIDDLE | WF_HSCROLL) ? FR_LOWERED : FR_NONE);
   392 
   394 
   393 			break;
   395 			break;
   394 		}
   396 		}
   395 
   397 
   396 		case WWT_FRAME: {
   398 		case WWT_FRAME: {
   397 			int c1,c2;
   399 			const StringID str = wi->data;
       
   400 			int c1, c2;
   398 			int x2 = r.left; // by default the left side is the left side of the widget
   401 			int x2 = r.left; // by default the left side is the left side of the widget
   399 
   402 
   400 			if (wi->data != 0) x2 = DrawString(r.left + 6, r.top, wi->data, 0);
   403 			if (str != STR_NULL) x2 = DrawString(r.left + 6, r.top, str, TC_FROMSTRING);
   401 
   404 
   402 			c1 = _colour_gradient[wi->color][3];
   405 			c1 = _colour_gradient[wi->color][3];
   403 			c2 = _colour_gradient[wi->color][7];
   406 			c2 = _colour_gradient[wi->color][7];
   404 
   407 
   405 			/*Line from upper left corner to start of text */
   408 			/* Line from upper left corner to start of text */
   406 			GfxFillRect(r.left, r.top+4, r.left+4,r.top+4, c1);
   409 			GfxFillRect(r.left, r.top + 4, r.left + 4, r.top + 4, c1);
   407 			GfxFillRect(r.left+1, r.top+5, r.left+4,r.top+5, c2);
   410 			GfxFillRect(r.left + 1, r.top + 5, r.left + 4, r.top + 5, c2);
   408 
   411 
   409 			/* Line from end of text to upper right corner */
   412 			/* Line from end of text to upper right corner */
   410 			GfxFillRect(x2, r.top+4, r.right-1,r.top+4,c1);
   413 			GfxFillRect(x2, r.top + 4, r.right - 1, r.top + 4, c1);
   411 			GfxFillRect(x2, r.top+5, r.right-2,r.top+5,c2);
   414 			GfxFillRect(x2, r.top + 5, r.right - 2, r.top + 5, c2);
   412 
   415 
   413 			/* Line from upper left corner to bottom left corner */
   416 			/* Line from upper left corner to bottom left corner */
   414 			GfxFillRect(r.left, r.top+5, r.left, r.bottom-1, c1);
   417 			GfxFillRect(r.left, r.top + 5, r.left, r.bottom - 1, c1);
   415 			GfxFillRect(r.left+1, r.top+6, r.left+1, r.bottom-2, c2);
   418 			GfxFillRect(r.left + 1, r.top + 6, r.left + 1, r.bottom - 2, c2);
   416 
   419 
   417 			/*Line from upper right corner to bottom right corner */
   420 			/*Line from upper right corner to bottom right corner */
   418 			GfxFillRect(r.right-1, r.top+5, r.right-1, r.bottom-2, c1);
   421 			GfxFillRect(r.right - 1, r.top + 5, r.right - 1, r.bottom - 2, c1);
   419 			GfxFillRect(r.right, r.top+4, r.right, r.bottom-1, c2);
   422 			GfxFillRect(r.right, r.top + 4, r.right, r.bottom - 1, c2);
   420 
   423 
   421 			GfxFillRect(r.left+1, r.bottom-1, r.right-1, r.bottom-1, c1);
   424 			GfxFillRect(r.left + 1, r.bottom - 1, r.right - 1, r.bottom - 1, c1);
   422 			GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2);
   425 			GfxFillRect(r.left, r.bottom, r.right, r.bottom, c2);
   423 
   426 
   424 			goto draw_default;
   427 			goto draw_default;
   425 		}
   428 		}
   426 
   429 
   427 		case WWT_STICKYBOX: {
   430 		case WWT_STICKYBOX: {
       
   431 			assert(wi->data == 0);
   428 			assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere!
   432 			assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere!
   429 
   433 
   430 			clicked = !!(w->flags4 & WF_STICKY);
   434 			clicked = !!(w->flags4 & WF_STICKY);
   431 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   435 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   432 			DrawSprite((clicked) ? SPR_PIN_UP : SPR_PIN_DOWN, PAL_NONE, r.left + 2 + clicked, r.top + 3 + clicked);
   436 			DrawSprite((clicked) ? SPR_PIN_UP : SPR_PIN_DOWN, PAL_NONE, r.left + 2 + clicked, r.top + 3 + clicked);
   433 			break;
   437 			break;
   434 		}
   438 		}
   435 
   439 
   436 		case WWT_RESIZEBOX: {
   440 		case WWT_RESIZEBOX: {
       
   441 			assert(wi->data == 0);
   437 			assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere!
   442 			assert(r.right - r.left == 11); // XXX - to ensure the same sizes are used everywhere!
   438 
   443 
   439 			clicked = !!(w->flags4 & WF_SIZING);
   444 			clicked = !!(w->flags4 & WF_SIZING);
   440 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   445 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, (clicked) ? FR_LOWERED : FR_NONE);
   441 			DrawSprite(SPR_WINDOW_RESIZE, PAL_NONE, r.left + 3 + clicked, r.top + 3 + clicked);
   446 			DrawSprite(SPR_WINDOW_RESIZE, PAL_NONE, r.left + 3 + clicked, r.top + 3 + clicked);
   442 			break;
   447 			break;
   443 		}
   448 		}
   444 
   449 
   445 		case WWT_CLOSEBOX: {
   450 		case WWT_CLOSEBOX: {
       
   451 			const StringID str = wi->data;
       
   452 
       
   453 			assert(str == STR_00C5 || str == STR_00C6); // black or silver cross
   446 			assert(r.right - r.left == 10); // ensure the same sizes are used everywhere
   454 			assert(r.right - r.left == 10); // ensure the same sizes are used everywhere
   447 
   455 
   448 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, FR_NONE);
   456 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, FR_NONE);
   449 			DrawString(r.left + 2, r.top + 2, STR_00C5, 0);
   457 			DrawString(r.left + 2, r.top + 2, str, TC_FROMSTRING);
   450 			break;
   458 			break;
   451 		}
   459 		}
   452 
   460 
   453 		case WWT_CAPTION: {
   461 		case WWT_CAPTION: {
   454 			assert(r.bottom - r.top == 13); // XXX - to ensure the same sizes are used everywhere!
   462 			assert(r.bottom - r.top == 13); // XXX - to ensure the same sizes are used everywhere!
   455 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, FR_BORDERONLY);
   463 			DrawFrameRect(r.left, r.top, r.right, r.bottom, wi->color, FR_BORDERONLY);
   456 			DrawFrameRect(r.left+1, r.top+1, r.right-1, r.bottom-1, wi->color, (w->caption_color == 0xFF) ? FR_LOWERED | FR_DARKENED : FR_LOWERED | FR_DARKENED | FR_BORDERONLY);
   464 			DrawFrameRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, wi->color, (w->caption_color == 0xFF) ? FR_LOWERED | FR_DARKENED : FR_LOWERED | FR_DARKENED | FR_BORDERONLY);
   457 
   465 
   458 			if (w->caption_color != 0xFF) {
   466 			if (w->caption_color != 0xFF) {
   459 				GfxFillRect(r.left+2, r.top+2, r.right-2, r.bottom-2, _colour_gradient[_player_colors[w->caption_color]][4]);
   467 				GfxFillRect(r.left + 2, r.top + 2, r.right - 2, r.bottom - 2, _colour_gradient[_player_colors[w->caption_color]][4]);
   460 			}
   468 			}
   461 
   469 
   462 			DrawStringCenteredTruncated(r.left + 2, r.right - 2, r.top+2, wi->data, 0x84);
   470 			DrawStringCenteredTruncated(r.left + 2, r.right - 2, r.top + 2, wi->data, 0x84);
   463 draw_default:;
   471 draw_default:;
   464 			if (IsWindowWidgetDisabled(w, i)) {
   472 			if (w->IsWidgetDisabled(i)) {
   465 				GfxFillRect(r.left+1, r.top+1, r.right-1, r.bottom-1, _colour_gradient[wi->color&0xF][2] | (1 << PALETTE_MODIFIER_GREYOUT));
   473 				GfxFillRect(r.left + 1, r.top + 1, r.right - 1, r.bottom - 1, _colour_gradient[wi->color & 0xF][2] | (1 << PALETTE_MODIFIER_GREYOUT));
   466 			}
   474 			}
   467 		}
   475 		}
   468 		}
   476 		}
   469 	}
   477 	}
   470 
   478 
   471 
   479 
   472 	if (w->flags4 & WF_WHITE_BORDER_MASK) {
   480 	if (w->flags4 & WF_WHITE_BORDER_MASK) {
   473 		//DrawFrameRect(w->left, w->top, w->left + w->width-1, w->top+w->height-1, 0xF, 0x10);
   481 		DrawFrameRect(0, 0, w->width - 1, w->height - 1, 0xF, FR_BORDERONLY);
   474 		DrawFrameRect(0, 0, w->width-1, w->height-1, 0xF, FR_BORDERONLY);
       
   475 	}
   482 	}
   476 
   483 
   477 }
   484 }
   478 
   485 
   479 static const Widget _dropdown_menu_widgets[] = {
   486 static const Widget _dropdown_menu_widgets[] = {
   494 
   501 
   495 	if (y < 0)
   502 	if (y < 0)
   496 		return - 1;
   503 		return - 1;
   497 
   504 
   498 	item = y / 10;
   505 	item = y / 10;
   499 	if (item >= WP(w,dropdown_d).num_items || (HASBIT(WP(w,dropdown_d).disabled_state, item) && !HASBIT(WP(w,dropdown_d).hidden_state, item)) || WP(w,dropdown_d).items[item] == 0)
   506 	if (item >= WP(w,dropdown_d).num_items || (HasBit(WP(w,dropdown_d).disabled_state, item) && !HasBit(WP(w,dropdown_d).hidden_state, item)) || WP(w,dropdown_d).items[item] == 0)
   500 		return - 1;
   507 		return - 1;
   501 
   508 
   502 	/* Skip hidden items -- +1 for each hidden item before the clicked item. */
   509 	/* Skip hidden items -- +1 for each hidden item before the clicked item. */
   503 	for (counter = 0; item >= counter; ++counter)
   510 	for (counter = 0; item >= counter; ++counter)
   504 		if (HASBIT(WP(w,dropdown_d).hidden_state, counter)) item++;
   511 		if (HasBit(WP(w,dropdown_d).hidden_state, counter)) item++;
   505 
   512 
   506 	return item;
   513 	return item;
   507 }
   514 }
   508 
   515 
   509 static void DropdownMenuWndProc(Window *w, WindowEvent *e)
   516 static void DropdownMenuWndProc(Window *w, WindowEvent *e)
   523 			sel    = WP(w,dropdown_d).selected_index;
   530 			sel    = WP(w,dropdown_d).selected_index;
   524 			width  = w->widget[0].right - 3;
   531 			width  = w->widget[0].right - 3;
   525 			height = w->widget[0].bottom - 3;
   532 			height = w->widget[0].bottom - 3;
   526 
   533 
   527 			for (i = 0; WP(w,dropdown_d).items[i] != INVALID_STRING_ID; i++, sel--) {
   534 			for (i = 0; WP(w,dropdown_d).items[i] != INVALID_STRING_ID; i++, sel--) {
   528 				if (HASBIT(WP(w,dropdown_d).hidden_state, i)) continue;
   535 				if (HasBit(WP(w,dropdown_d).hidden_state, i)) continue;
   529 
   536 
   530 				if (y >= 0 && y <= height) {
   537 				if (y >= 0 && y <= height) {
   531 					if (WP(w,dropdown_d).items[i] != STR_NULL) {
   538 					if (WP(w,dropdown_d).items[i] != STR_NULL) {
   532 						if (sel == 0) GfxFillRect(x + 1, y, x + width, y + 9, 0);
   539 						if (sel == 0) GfxFillRect(x + 1, y, x + width, y + 9, 0);
   533 						DrawStringTruncated(x + 2, y, WP(w,dropdown_d).items[i], sel == 0 ? 12 : 16, x + width);
   540 						DrawStringTruncated(x + 2, y, WP(w,dropdown_d).items[i], sel == 0 ? TC_WHITE : TC_BLACK, x + width);
   534 
   541 
   535 						if (HASBIT(WP(w,dropdown_d).disabled_state, i)) {
   542 						if (HasBit(WP(w,dropdown_d).disabled_state, i)) {
   536 							GfxFillRect(x, y, x + width, y + 9,
   543 							GfxFillRect(x, y, x + width, y + 9,
   537 								(1 << PALETTE_MODIFIER_GREYOUT) | _colour_gradient[_dropdown_menu_widgets[0].color][5]
   544 								(1 << PALETTE_MODIFIER_GREYOUT) | _colour_gradient[_dropdown_menu_widgets[0].color][5]
   538 							);
   545 							);
   539 						}
   546 						}
   540 					} else {
   547 					} else {
   593 		} break;
   600 		} break;
   594 
   601 
   595 		case WE_DESTROY: {
   602 		case WE_DESTROY: {
   596 			Window *w2 = FindWindowById(WP(w,dropdown_d).parent_wnd_class, WP(w,dropdown_d).parent_wnd_num);
   603 			Window *w2 = FindWindowById(WP(w,dropdown_d).parent_wnd_class, WP(w,dropdown_d).parent_wnd_num);
   597 			if (w2 != NULL) {
   604 			if (w2 != NULL) {
   598 				RaiseWindowWidget(w2, WP(w,dropdown_d).parent_button);
   605 				w2->RaiseWidget(WP(w,dropdown_d).parent_button);
   599 				InvalidateWidget(w2, WP(w,dropdown_d).parent_button);
   606 				InvalidateWidget(w2, WP(w,dropdown_d).parent_button);
   600 			}
   607 			}
   601 		} break;
   608 		} break;
   602 	}
   609 	}
   603 }
   610 }
   606 {
   613 {
   607 	int i;
   614 	int i;
   608 	const Widget *wi;
   615 	const Widget *wi;
   609 	Window *w2;
   616 	Window *w2;
   610 	const Window *w3;
   617 	const Window *w3;
   611 	bool is_dropdown_menu_shown = IsWindowWidgetLowered(w, button);
   618 	bool is_dropdown_menu_shown = w->IsWidgetLowered(button);
   612 	int top, height;
   619 	int top, height;
   613 	int screen_top, screen_bottom;
   620 	int screen_top, screen_bottom;
   614 	bool scroll = false;
   621 	bool scroll = false;
   615 
   622 
   616 	DeleteWindowById(WC_DROPDOWN_MENU, 0);
   623 	DeleteWindowById(WC_DROPDOWN_MENU, 0);
   617 
   624 
   618 	if (is_dropdown_menu_shown) return;
   625 	if (is_dropdown_menu_shown) return;
   619 
   626 
   620 	LowerWindowWidget(w, button);
   627 	w->LowerWidget(button);
   621 
   628 
   622 	InvalidateWidget(w, button);
   629 	InvalidateWidget(w, button);
   623 
   630 
   624 	for (i = 0; strings[i] != INVALID_STRING_ID; i++) {}
   631 	for (i = 0; strings[i] != INVALID_STRING_ID; i++) {}
   625 	if (i == 0) return;
   632 	if (i == 0) return;
   628 
   635 
   629 	if (hidden_mask != 0) {
   636 	if (hidden_mask != 0) {
   630 		uint j;
   637 		uint j;
   631 
   638 
   632 		for (j = 0; strings[j] != INVALID_STRING_ID; j++) {
   639 		for (j = 0; strings[j] != INVALID_STRING_ID; j++) {
   633 			if (HASBIT(hidden_mask, j)) i--;
   640 			if (HasBit(hidden_mask, j)) i--;
   634 		}
   641 		}
   635 	}
   642 	}
   636 
   643 
   637 	/* The preferred position is just below the dropdown calling widget */
   644 	/* The preferred position is just below the dropdown calling widget */
   638 	top = w->top + wi->bottom + 2;
   645 	top = w->top + wi->bottom + 2;
   669 
   676 
   670 	w2->widget[0].color = wi->color;
   677 	w2->widget[0].color = wi->color;
   671 	w2->widget[0].right = wi->right - wi[-1].left;
   678 	w2->widget[0].right = wi->right - wi[-1].left;
   672 	w2->widget[0].bottom = height - 1;
   679 	w2->widget[0].bottom = height - 1;
   673 
   680 
   674 	SetWindowWidgetHiddenState(w2, 1, !scroll);
   681 	w2->SetWidgetHiddenState(1, !scroll);
   675 
   682 
   676 	if (scroll) {
   683 	if (scroll) {
   677 		/* We're scrolling, so enable the scroll bar and shrink the list by
   684 		/* We're scrolling, so enable the scroll bar and shrink the list by
   678 		 * the scrollbar's width */
   685 		 * the scrollbar's width */
   679 		w2->widget[1].color  = wi->color;
   686 		w2->widget[1].color  = wi->color;