Exemple #1
0
void format_string_part_from_raw(utf8 **dest, const utf8 *src, char **args)
{
	unsigned int code;
	while (1) {
		code = utf8_get_next(src, &src);
		if (code < ' ') {
			if (code == 0) {
				*(*dest)++ = code;
				break;
			} else if (code <= 4) {
				*(*dest)++ = code;
				*(*dest)++ = *src++;
			} else if (code <= 16) {
				*(*dest)++ = code;
			} else if (code <= 22) {
				*(*dest)++ = code;
				*(*dest)++ = *src++;
				*(*dest)++ = *src++;
			} else {
				*(*dest)++ = code;
				*(*dest)++ = *src++;
				*(*dest)++ = *src++;
				*(*dest)++ = *src++;
				*(*dest)++ = *src++;
			}
		} else if (code <= 'z') {
			*(*dest)++ = code;
		} else if (code < FORMAT_COLOUR_CODE_START || code == FORMAT_COMMA1DP16) {
			format_string_code(code, dest, args);
		} else {
			*dest = utf8_write_codepoint(*dest, code);
		}
	}
}
void textinputbuffer_insert(textinputbuffer * tib, utf8 * source)
{
	const utf8 *ch = source;
	uint32 codepoint;
	while ((codepoint = utf8_get_next(ch, &ch)) != 0) {
		textinputbuffer_insert_codepoint(tib, codepoint);
	}
}
static int32_t large_scenery_sign_text_height(const utf8* str, rct_large_scenery_text* text)
{
    int32_t height = 0;
    uint32_t codepoint;
    while ((codepoint = utf8_get_next(str, &str)) != 0)
    {
        height += large_scenery_sign_get_glyph(text, codepoint)->height;
    }
    return height;
}
static int32_t large_scenery_sign_text_width(const utf8* str, rct_large_scenery_text* text)
{
    int32_t width = 0;
    uint32_t codepoint;
    while ((codepoint = utf8_get_next(str, &str)) != 0)
    {
        width += large_scenery_sign_get_glyph(text, codepoint)->width;
    }
    return width;
}
Exemple #5
0
bool font_supports_string_sprite(const utf8 *text)
{
    const utf8 *src = text;

    uint32 codepoint;
    while ((codepoint = utf8_get_next(src, &src)) != 0) {
        bool supported = false;
        switch (codepoint) {
        case FORMAT_ENDQUOTES:
        case FORMAT_AMINUSCULE:
        case FORMAT_UP:
        case FORMAT_SYMBOL_i:
        case FORMAT_CENT:
        case FORMAT_POUND:
        case FORMAT_YEN:
        case FORMAT_COPYRIGHT:
        case FORMAT_DOWN:
        case FORMAT_LEFTGUILLEMET:
        case FORMAT_TICK:
        case FORMAT_CROSS:
        case FORMAT_RIGHT:
        case FORMAT_DEGREE:
        case FORMAT_SYMBOL_RAILWAY:
        case FORMAT_SQUARED:
        case FORMAT_OPENQUOTES:
        case FORMAT_EURO:
        case FORMAT_SYMBOL_ROAD:
        case FORMAT_SYMBOL_FLAG:
        case FORMAT_APPROX:
        case FORMAT_POWERNEGATIVEONE:
        case FORMAT_BULLET:
        case FORMAT_RIGHTGUILLEMET:
        case FORMAT_SMALLUP:
        case FORMAT_SMALLDOWN:
        case FORMAT_LEFT:
        case FORMAT_INVERTEDQUESTION:
            supported = true;
            break;
        default:
            if (codepoint >= 32 && codepoint < 256) {
                supported = true;
            }
            break;
        }
        if (!supported) {
            return false;
        }
    }
    return true;
}
Exemple #6
0
bool font_supports_string_ttf(const utf8 *text, int fontSize)
{
    const utf8 *src = text;
    const TTF_Font *font = gCurrentTTFFontSet->size[fontSize].font;

    uint32 codepoint;
    while ((codepoint = utf8_get_next(src, &src)) != 0) {
        bool supported = TTF_GlyphIsProvided(font, (uint16)codepoint);
        if (!supported) {
            return false;
        }
    }
    return true;
}
Exemple #7
0
void scrolling_text_set_bitmap_for_sprite(utf8 *text, sint32 scroll, uint8 *bitmap, const sint16 *scrollPositionOffsets)
{
	uint8 characterColour = scrolling_text_get_colour(gCommonFormatArgs[7]);

	utf8 *ch = text;
	while (true) {
		uint32 codepoint = utf8_get_next(ch, (const utf8**)&ch);

		// If at the end of the string loop back to the start
		if (codepoint == 0) {
			ch = text;
			continue;
		}

		// Set any change in colour
		if (codepoint <= FORMAT_COLOUR_CODE_END && codepoint >= FORMAT_COLOUR_CODE_START){
			codepoint -= FORMAT_COLOUR_CODE_START;
			characterColour = g1Elements[SPR_TEXT_PALETTE].offset[codepoint * 4];
			continue;
		}

		// If another type of control character ignore
		if (codepoint < 32) continue;

		sint32 characterWidth = font_sprite_get_codepoint_width(FONT_SPRITE_BASE_TINY, codepoint);
		uint8 *characterBitmap = font_sprite_get_codepoint_bitmap(codepoint);
		for (; characterWidth != 0; characterWidth--, characterBitmap++) {
			// Skip any none displayed columns
			if (scroll != 0) {
				scroll--;
				continue;
			}

			sint16 scrollPosition = *scrollPositionOffsets;
			if (scrollPosition == -1) return;
			if (scrollPosition > -1) {
				uint8 *dst = &bitmap[scrollPosition];
				for (uint8 char_bitmap = *characterBitmap; char_bitmap != 0; char_bitmap >>= 1){
					if (char_bitmap & 1) *dst = characterColour;

					// Jump to next row
					dst += 64;
				}
			}
			scrollPositionOffsets++;
		}
	}
Exemple #8
0
void chat_history_add(const char* src)
{
    size_t bufferSize = strlen(src) + 64;
    utf8* buffer = (utf8*)calloc(1, bufferSize);

    // Find the start of the text (after format codes)
    const char* ch = src;
    const char* nextCh;
    uint32_t codepoint;
    while ((codepoint = utf8_get_next(ch, &nextCh)) != 0)
    {
        if (!utf8_is_format_code(codepoint))
        {
            break;
        }
        ch = nextCh;
    }
    const char* srcText = ch;

    // Copy format codes to buffer
    std::memcpy(buffer, src, std::min(bufferSize, (size_t)(srcText - src)));

    // Prepend a timestamp
    time_t timer;
    time(&timer);
    struct tm* tmInfo = localtime(&timer);

    strcatftime(buffer, bufferSize, "[%H:%M] ", tmInfo);
    safe_strcat(buffer, srcText, bufferSize);

    // Add to history list
    int32_t index = _chatHistoryIndex % CHAT_HISTORY_SIZE;
    std::fill_n(_chatHistory[index], CHAT_INPUT_SIZE, 0x00);
    std::memcpy(_chatHistory[index], buffer, std::min<size_t>(strlen(buffer), CHAT_INPUT_SIZE - 1));
    _chatHistoryTime[index] = platform_get_ticks();
    _chatHistoryIndex++;

    // Log to file (src only as logging does its own timestamp)
    network_append_chat_log(src);

    free(buffer);

    Mixer_Play_Effect(SOUND_NEWS_ITEM, 0, MIXER_VOLUME_MAX, 0.5f, 1.5f, true);
}
static const utf8* large_scenery_sign_fit_text(const utf8* str, rct_large_scenery_text* text, bool height)
{
    static utf8 fitStr[32];
    utf8* fitStrEnd = fitStr;
    safe_strcpy(fitStr, str, sizeof(fitStr));
    int32_t w = 0;
    uint32_t codepoint;
    while (w <= text->max_width && (codepoint = utf8_get_next(fitStrEnd, (const utf8**)&fitStrEnd)) != 0)
    {
        if (height)
        {
            w += large_scenery_sign_get_glyph(text, codepoint)->height;
        }
        else
        {
            w += large_scenery_sign_get_glyph(text, codepoint)->width;
        }
    }
    *fitStrEnd = 0;
    return fitStr;
}
Exemple #10
0
bool font_supports_string_ttf(const utf8 *text, sint32 fontSize)
{
#ifndef NO_TTF
    const utf8 *src = text;
    const TTF_Font *font = gCurrentTTFFontSet->size[fontSize].font;
    if (font == NULL) {
        return false;
    }

    uint32 codepoint;
    while ((codepoint = utf8_get_next(src, &src)) != 0) {
        bool supported = ttf_provides_glyph(font, codepoint);
        if (!supported) {
            return false;
        }
    }
    return true;
#else
    return false;
#endif // NO_TTF
}
static void large_scenery_sign_paint_line(
    paint_session* session, const utf8* str, rct_large_scenery_text* text, int32_t textImage, int32_t textColour,
    uint8_t direction, int32_t y_offset)
{
    const utf8* fitStr = large_scenery_sign_fit_text(str, text, false);
    int32_t width = large_scenery_sign_text_width(fitStr, text);
    int32_t x_offset = text->offset[(direction & 1)].x;
    int32_t acc = y_offset * ((direction & 1) ? -1 : 1);
    if (!(text->flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL))
    {
        // sign is horizontal, centre text:
        x_offset -= (width / 2);
        acc -= (width / 2);
    }
    uint32_t codepoint;
    while ((codepoint = utf8_get_next(fitStr, &fitStr)) != 0)
    {
        int32_t glyph_offset = large_scenery_sign_get_glyph(text, codepoint)->image_offset;
        uint8_t glyph_type = direction & 1;
        if (text->flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL)
        { // vertical sign
            glyph_offset *= 2;
        }
        else
        {
            glyph_offset *= 4;
            // set slightly different glyph on horizontal sign, which was rendered 1/2 pixel lower to deal with aliasing:
            if (direction & 1)
            {
                if (!(acc & 1))
                {
                    glyph_type += 2;
                }
            }
            else
            {
                if ((acc & 1))
                {
                    glyph_type += 2;
                }
            }
        }
        int32_t image_id = (textImage + glyph_offset + glyph_type) | textColour;
        if (direction == 3)
        {
            paint_attach_to_previous_ps(session, image_id, x_offset, -div_to_minus_infinity(acc, 2));
        }
        else
        {
            if (text->flags & LARGE_SCENERY_TEXT_FLAG_VERTICAL)
            {
                paint_attach_to_previous_ps(session, image_id, x_offset, div_to_minus_infinity(acc, 2));
            }
            else
            {
                paint_attach_to_previous_attach(session, image_id, x_offset, div_to_minus_infinity(acc, 2));
            }
        }
        x_offset += large_scenery_sign_get_glyph(text, codepoint)->width;
        acc += large_scenery_sign_get_glyph(text, codepoint)->width;
    }
}
Exemple #12
0
static money32 BannerSetStyle(uint8 bannerIndex, uint8 colour, uint8 textColour, uint8 bannerFlags, uint8 flags)
{
    if (bannerIndex >= MAX_BANNERS)
    {
        gGameCommandErrorText = STR_INVALID_SELECTION_OF_OBJECTS;
        return MONEY32_UNDEFINED;
    }

    rct_banner* banner = &gBanners[bannerIndex];

    rct_tile_element* tileElement = banner_get_tile_element(bannerIndex);

    if (tileElement == nullptr)
    {
        return MONEY32_UNDEFINED;
    }

    if (!(flags & GAME_COMMAND_FLAG_APPLY))
    {
        return 0;
    }

    banner->colour = colour;
    banner->text_colour = textColour;
    banner->flags = bannerFlags;

    tileElement->properties.banner.flags = 0xFF;
    if (banner->flags & BANNER_FLAG_NO_ENTRY)
    {
        tileElement->properties.banner.flags &= ~(1 << tileElement->properties.banner.position);
    }

    sint32 colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour;

    utf8 buffer[256];
    format_string(buffer, 256, banner->string_idx, nullptr);
    sint32 firstCodepoint = utf8_get_next(buffer, nullptr);
    if (firstCodepoint >= FORMAT_COLOUR_CODE_START && firstCodepoint <= FORMAT_COLOUR_CODE_END)
    {
        utf8_write_codepoint(buffer, colourCodepoint);
    }
    else
    {
        utf8_insert_codepoint(buffer, colourCodepoint);
    }

    rct_string_id stringId = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer);
    if (stringId != 0)
    {
        rct_string_id prevStringId = banner->string_idx;
        banner->string_idx = stringId;
        user_string_free(prevStringId);

        auto intent = Intent(INTENT_ACTION_UPDATE_BANNER);
        intent.putExtra(INTENT_EXTRA_BANNER_INDEX, bannerIndex);
        context_broadcast_intent(&intent);
    }
    else
    {
        gGameCommandErrorText = STR_ERR_CANT_SET_BANNER_TEXT;
        return MONEY32_UNDEFINED;
    }

    return 0;
}
Exemple #13
0
static void window_text_input_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
	window_draw_widgets(w, dpi);

	sint32 y = w->y + 25;

	sint32 no_lines = 0;
	sint32 font_height = 0;


	gfx_draw_string_centred(dpi, input_text_description, w->x + WW / 2, y, w->colours[1], &TextInputDescriptionArgs);

	y += 25;

	gCurrentFontSpriteBase = FONT_SPRITE_BASE_MEDIUM;
	gCurrentFontFlags = 0;

	char wrapped_string[512];
	safe_strcpy(wrapped_string, text_input, 512);

	// String length needs to add 12 either side of box
	// +13 for cursor when max length.
	gfx_wrap_string(wrapped_string, WW - (24 + 13), &no_lines, &font_height);

	gfx_fill_rect_inset(dpi, w->x + 10, y, w->x + WW - 10, y + 10 * (no_lines + 1) + 3, w->colours[1], INSET_RECT_F_60);

	y += 1;

	char* wrap_pointer = wrapped_string;
	size_t char_count = 0;
	uint8 cur_drawn = 0;

	sint32 cursorX = 0, cursorY = 0;
	for (sint32 line = 0; line <= no_lines; line++) {
		gfx_draw_string(dpi, wrap_pointer, w->colours[1], w->x + 12, y);

		size_t string_length = get_string_size(wrap_pointer) - 1;

		if (!cur_drawn && (gTextInput.selection_offset <= char_count + string_length)) {
			// Make a copy of the string for measuring the width.
			char temp_string[512] = { 0 };
			memcpy(temp_string, wrap_pointer, gTextInput.selection_offset - char_count);
			cursorX = w->x + 13 + gfx_get_string_width(temp_string);
			cursorY = y;

			sint32 width = 6;
			if (gTextInput.selection_offset < strlen(text_input)){
				// Make a 1 utf8-character wide string for measuring the width
				// of the currently selected character.
				utf8 tmp[5] = { 0 }; // This is easier than setting temp_string[0..5]
				uint32 codepoint = utf8_get_next(text_input + gTextInput.selection_offset, NULL);
				utf8_write_codepoint(tmp, codepoint);
				width = max(gfx_get_string_width(tmp) - 2, 4);
			}

			if (w->frame_no > 15){
				uint8 colour = ColourMapA[w->colours[1]].mid_light;
				gfx_fill_rect(dpi, cursorX, y + 9, cursorX + width, y + 9, colour + 5);
			}

			cur_drawn++;
		}

		wrap_pointer += string_length + 1;

		if (text_input[char_count + string_length] == ' ')char_count++;
		char_count += string_length;

		y += 10;
	}

	if (!cur_drawn) {
		cursorX = gLastDrawStringX;
		cursorY = y - 10;
	}

	// IME composition
	if (gTextInputCompositionActive) {
		draw_ime_composition(dpi, cursorX, cursorY);
	}
}