예제 #1
0
//	Process the main text into lines that fix into the pop-up window
//
void Achievement::prepare(int win_x, int font_x, int border)
{
	if (prepared)
		return;
	prepared = true;

	int col = 0;
	std::string::size_type last_space = 0;
	std::string::size_type start = 0;
	int chars_per_line = (win_x - 2 * border) / font_x;

	for (std::string::size_type i=0; i<text.size(); i++)
	{
		if (is_color(text[i]))
			continue;
		if (text[i] == ' ')
			last_space = i;
		if (col >= chars_per_line)
		{
			lines.push_back(text.substr(start, last_space-start));
			start = last_space+1;
			col = i - start;
		}
		col++;
	}

	if (start < text.size())
		lines.push_back(text.substr(start, text.size()-start));
}
예제 #2
0
파일: text.c 프로젝트: regnauld/citaa
void
extract_text(struct image *img)
{
	int y, x, sx;
	CHAR *buf, *s;
	struct rgb rgb;
	struct component *c, *last_c = NULL;
	int shape;
	struct text *t, *last_t = NULL;

	buf = malloc(sizeof(CHAR)*img->w);
	if (!buf)	croak(1, "extract_text:malloc(buf)");

	for (y = 0; y < img->h; y++) {
		last_c = NULL;
		last_t = NULL;
		for (x = 0; x < img->w; x++) {
			s = buf;
			sx = x;

			while (img->d[y][x] != ' ' && component_marks->d[y][x] == ' ') {
				*s++ = img->d[y][x++];
			}
			*s = '\0';
			if (s != buf) {
				printf("%d,%d: |%s|\n", y, sx, buf);
				c = find_enclosing_component(&components, y, sx);
				if (is_color(buf, &rgb) && c) {
					double percepted_luminance = 1 - ( 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b)/0xF;

					c->has_custom_background = 1;
					c->custom_background = rgb;
					if (percepted_luminance >= 0.5)
						c->white_text = 1;
					printf("COLOR %x%x%x\n", rgb.r, rgb.g, rgb.b);
				} else if (is_shape(buf, &shape) && c) {
					c->shape = shape;
				} else {
					if (last_t && last_c == c &&
						sx > 0 && img->d[y][sx-1] == ' ' &&
						last_t->x + last_t->len + 1 == sx)
					{
						extend_text(last_t, 1, buf);
					} else {
						t = create_text(y, sx, buf);
						TAILQ_INSERT_TAIL(c ? &c->text : &free_text, t, list);
						last_c = c;
						last_t = t;
					}
				}
			}
		}
	}
	free(buf);
}
예제 #3
0
void LevelGen::generate_map()
{
	typedef std::map<std::string, sf::Color*>::iterator it_type;

	//- map is always named map.png in the level folder
	sf::Image map;
	map.loadFromFile(this->path+"map.png");

	size = map.getSize();

	std::cout << "Loaded map size\n";

	sf::Clock timer;
	for(int i = 0; i < size.x*size.y; ++i)

	{
		int x = (int)i%size.x, y = (int)floor(i/size.x);
		sf::Color color = map.getPixel(x, y);

		//- Set tiles based on colors in the map
		if(is_color(color, 255, 255, 255))
			tiles.push_back(new Tile(x, y, false, txmgr.get_ref("floor.png")));
		else if(is_color(color, 0, 0, 0))
			tiles.push_back(new Tile(x, y, true, txmgr.get_ref("wall.png")));
		else{
			if(custom_tiles.size() < 1){continue;}
			for(it_type iterator = custom_tiles.begin(); iterator != custom_tiles.end(); iterator++)
			{
				if(is_color(color, (int)iterator->second->r, (int)iterator->second->g, (int)iterator->second->b))
					tiles.push_back(new Tile(x, y, txmgr.get_ref(iterator->first)));
			}
		}
	}

	std::cout << "Level constructed in [" << timer.restart().asMilliseconds() << "] with a total of [" << tiles.size() << "] tiles\n";

}
예제 #4
0
void print_string_escaped (const char *str)
{
	int i;

	for (i=0; str[i]; i++)
	{
		if (str[i]=='\r')
			printf ("\\r");
		else if (str[i] == '\n')
			printf ("\\n\n");
		else if (!is_color (str[i]))
			printf ("%c", str[i]);
	}

	printf ("\nlen = %d\n", i);
}
예제 #5
0
// converts a character into which entry in font.bmp to use, negative on error or no output
int find_font_char (unsigned char cur_char)
{
	if (is_color (cur_char))
	{
		float r,g,b;
		//must be a color
		int color = from_color_char (cur_char);
		r = (float) colors_list[color].r1 / 255.0f;
		g = (float) colors_list[color].g1 / 255.0f;
		b = (float) colors_list[color].b1 / 255.0f;
		//This fixes missing letters in the font on some clients
		//No idea why going from 3f to 4f helps, but it does
		glColor4f(r,g,b,1.0);
		return(-1);	// nothing to do
	}
	return(get_font_char(cur_char));
}
예제 #6
0
static const char *
actual_color(const char *param, int len, int arg)
{
    const char *result;
    char *s = strmalloc(param);

    if (len > 0) {		/* if not null-terminated, set it now */
	s[len] = '\0';
    }

    result = color_of(s, arg);
    if (*result == 0)
	result = keyword_attr(s);

    if (result != 0 && *result != 0 && !is_color(result)) {
	result = Literal_attr;
    }

    free(s);
    return result;
}
예제 #7
0
// Searches for terminating characters based on type, from "input_text", adding them to "name"
int get_name_from_text(const char * input_text, int len, int type, int offset, char * name)
{
	int i, do_break;
	Uint8 ch;
	
	for (i = 0; i < MAX_USERNAME_LENGTH - 1 && (i + offset) < len; i++)
	{
		ch = input_text[i+offset];	//skip over the prefix
		do_break = 0;
		switch (type)
		{
			case 0:
				if (ch == ':' || ch == ' ')
					do_break = 1;
				break;
			case 1:
				if (ch == ':' || ch == ' ' || is_color (ch))
					do_break = 1;
				break;
			case 2:
				if (isspace(ch))
					do_break = 1;
				break;
			case 3:
				if (ch == ':' || ch == ' ' || ch == ']')
					do_break = 1;
				break;
			case 4:
				if (ch == ':' || ch == '-' || ch == ' ')
					do_break = 1;
				break;
		}
		if (do_break == 1)
			break;
		name[i] = ch;
	}
	name[i] = '\0';
	return i;
}
예제 #8
0
파일: buddy.c 프로젝트: pjbroad/other-life
int is_in_buddylist(const char *name)
{
	int i;
	char onlyname[32];
	if(!name || !*name) {
		return 0;
	}
	while(name[0] != '\0' && is_color ((unsigned char)name[0])){
		++name;
	}
	// strip GuildTag if existing
	for(i = 0; name[i]>32; i++){
		onlyname[i] = name[i];
	}
	onlyname[i] = '\0';

	for(i = 0; i < MAX_BUDDY; i++) {
		if(buddy_list[i].type < 0xff && strcasecmp(buddy_list[i].name, onlyname) == 0) {
			return 1;
		}
	}
	return 0;
}
예제 #9
0
clan::Colorf SvgAttributeReader::get_color()
{
	if (!is_color()) parse_error("expected color");

	size_t end_pos = pos + 1;
	while (end_pos < attr.length())
	{
		bool is_hex_char = (attr[end_pos] >= 'a' && attr[end_pos] <= 'f') || (attr[end_pos] >= 'A' && attr[end_pos] <= 'F') || (attr[end_pos] >= '0' && attr[end_pos] <= '9');
		if (!is_hex_char) break;
		end_pos++;
	}

	if (end_pos != pos + 4 && end_pos != pos + 7) parse_error("invalid color");

	clan::Colorf color;
	std::string hexstr = attr.substr(pos + 1, end_pos - pos - 1);
	unsigned int value = strtoul(hexstr.c_str(), 0, 16);
	if (end_pos == pos + 4)
	{
		int red = ((((value >> 8) & 0xf) + 1) << 4) - 1;
		int green = ((((value >> 4) & 0xf) + 1) << 4) - 1;
		int blue = (((value & 0xf) + 1) << 4) - 1;
		color = clan::Colorf(red / 255.0f, green / 255.0f, blue / 255.0f);
	}
예제 #10
0
void put_colored_text_in_buffer (Uint8 color, Uint8 channel, const Uint8 *text_to_add, int len)
{
	text_message *msg;
	int minlen, text_color;
	Uint32 cnr = 0, ibreak = -1, jbreak = -1;
	char time_stamp[12];
	struct tm *l_time; time_t c_time;

	check_chat_text_to_overtext (text_to_add, len, channel);

	// check for auto-length
	if (len < 0)
		len = strlen ((char*)text_to_add);

	// set the time when we got this message
	last_server_message_time = cur_time;

	// if the buffer is full, delete some old lines and move the remainder to the front
	if (++last_message >= DISPLAY_TEXT_BUFFER_SIZE)
	{
		const size_t num_move = DISPLAY_TEXT_BUFFER_SIZE - DISPLAY_TEXT_BUFFER_DEL;
		size_t i;
		for (i=0; i<DISPLAY_TEXT_BUFFER_DEL; i++)
		{
			msg = &(display_text_buffer[i]);
			if (msg->data)
			{
				msg->deleted = 1;
				update_text_windows(msg);
				free_text_message_data (msg);
			}
		}
		memmove(display_text_buffer, &display_text_buffer[DISPLAY_TEXT_BUFFER_DEL], sizeof(text_message)*num_move);
		last_message -= DISPLAY_TEXT_BUFFER_DEL;
		for (i = num_move; i < DISPLAY_TEXT_BUFFER_SIZE; i++)
			init_text_message (display_text_buffer + i, 0);
	}

	msg = &(display_text_buffer[last_message]);

	// Try to make a guess at the number of wrapping newlines required,
	// but allow al least for a null byte and up to 8 extra newlines and
	// colour codes
	minlen = len + 18 + (len/60);
	if (show_timestamp)
	{
		minlen += 12;
		time (&c_time);
		l_time = localtime (&c_time);
		strftime (time_stamp, sizeof(time_stamp), "[%H:%M:%S] ", l_time);
	}
	cnr = get_active_channel (channel);
	if (cnr != 0)
		// allow some space for the channel number
		minlen += 20;
	if (msg->data == NULL)
		alloc_text_message_data (msg, minlen);
	else
		resize_text_message_data (msg, minlen);

	if (cnr != 0)
	{
		for (ibreak = 0; ibreak < len; ibreak++)
		{
			if (text_to_add[ibreak] == ']') break;
		}
	}

	if (channel == CHAT_LOCAL)
	{
		for (jbreak = 0; jbreak < len; jbreak++)
		{
			if (text_to_add[jbreak] == ':' && text_to_add[jbreak+1] == ' ') break;
		}
	}

	if (dark_channeltext==1)
		text_color = c_grey2;
	else if (dark_channeltext==2)
		text_color = c_grey4;

	if (ibreak >= len)
	{
		// not a channel, or something's messed up
		if(!is_color (text_to_add[0]))
		{
			// force the color
			if (show_timestamp)
			{
				safe_snprintf (msg->data, msg->size, "%c%s%.*s", to_color_char (color), time_stamp, len, text_to_add);
			}
			else
			{
				safe_snprintf (msg->data, msg->size, "%c%.*s", to_color_char (color), len, text_to_add);
			}
		}
		else
		{
			// color set by server
			if (show_timestamp)
			{
				if(dark_channeltext && channel==CHAT_LOCAL && from_color_char(text_to_add[0])==c_grey1 && jbreak < (len-3))
				{
					safe_snprintf (msg->data, msg->size, "%c%s%.*s%.*s", to_color_char (text_color), time_stamp, jbreak+1, &text_to_add[1], len-jbreak-3, &text_to_add[jbreak+3]);
				}
				else
				{
					safe_snprintf (msg->data, msg->size, "%c%s%.*s", text_to_add[0], time_stamp, len-1, &text_to_add[1]);
				}
			}
			else
			{
				if(dark_channeltext && channel==CHAT_LOCAL && from_color_char(text_to_add[0])==c_grey1 && jbreak < (len-3))
				{
					safe_snprintf (msg->data, msg->size, "%c%.*s%.*s", to_color_char (text_color), jbreak+1, &text_to_add[1], len-jbreak-3, &text_to_add[jbreak+3]);
				}
				else
				{
					safe_snprintf (msg->data, msg->size, "%.*s", len, text_to_add);
				}
			}
		}
	}
	else
	{
		char nr_str[16];
		int has_additional_color = is_color(text_to_add[ibreak+3]);
		if (cnr >= 1000000000)
			safe_snprintf (nr_str, sizeof (nr_str), "guild");
		else
			safe_snprintf (nr_str, sizeof (nr_str), "%u", cnr);

		if(!is_color (text_to_add[0]))
		{
			// force the color
			if (show_timestamp)
			{
				if (dark_channeltext)
				{
					safe_snprintf (msg->data, msg->size, "%c%s%.*s @ %s%.*s%c%.*s", to_color_char (color), time_stamp, ibreak, text_to_add, nr_str, 3, &text_to_add[ibreak], to_color_char (text_color), len-ibreak-3-has_additional_color, &text_to_add[ibreak+3+has_additional_color]);
				}
				else
				{
					safe_snprintf (msg->data, msg->size, "%c%s%.*s @ %s%.*s", to_color_char (color), time_stamp, ibreak, text_to_add, nr_str, len-ibreak, &text_to_add[ibreak]);
				}
			}
			else
			{
				if (dark_channeltext)
				{
					safe_snprintf (msg->data, msg->size, "%c%.*s @ %s%.*s%c%.*s", to_color_char (color), ibreak, text_to_add, nr_str, 3, &text_to_add[ibreak], to_color_char (text_color), len-ibreak-3-has_additional_color, &text_to_add[ibreak+3+has_additional_color]);
				}
				else
				{
					safe_snprintf (msg->data, msg->size, "%c%.*s @ %s%.*s", to_color_char (color), ibreak, text_to_add, nr_str, len-ibreak, &text_to_add[ibreak]);
				}
			}
		}
		else
		{
			// color set by server
			if (show_timestamp)
			{
				if (dark_channeltext)
				{
					safe_snprintf (msg->data, msg->size, "%c%s%.*s @ %s%.*s%c%.*s", text_to_add[0], time_stamp, ibreak-1, &text_to_add[1], nr_str, 3, &text_to_add[ibreak], to_color_char (text_color), len-ibreak-3-has_additional_color, &text_to_add[ibreak+3+has_additional_color]);
				}
				else
				{
					safe_snprintf (msg->data, msg->size, "%c%s%.*s @ %s%.*s", text_to_add[0], time_stamp, ibreak-1, &text_to_add[1], nr_str, len-ibreak, &text_to_add[ibreak]);
				}
			}
			else
			{
				if (dark_channeltext)
				{
					safe_snprintf (msg->data, msg->size, "%.*s @ %s%.*s%c%.*s", ibreak, text_to_add, nr_str, 3, &text_to_add[ibreak], to_color_char (text_color), len-ibreak-3-has_additional_color, &text_to_add[ibreak+3+has_additional_color]);
				}
				else
				{
					safe_snprintf (msg->data, msg->size, "%.*s @ %s%.*s", ibreak, text_to_add, nr_str, len-ibreak, &text_to_add[ibreak]);
				}
			}
		}
	}

	msg->len = strlen (msg->data);
	msg->chan_idx = channel;
	msg->channel = cnr;

	// set invalid wrap data to force rewrapping
	msg->wrap_lines = 0;
	msg->wrap_zoom = 0.0f;
	msg->wrap_width = 0;

	msg->deleted = 0;
	recolour_message(msg);
	update_text_windows(msg);

	// log the message
	write_to_log (channel, (unsigned char*)msg->data, msg->len);

	return;
}
예제 #11
0
int filter_or_ignore_text (char *text_to_add, int len, int size, Uint8 channel)
{
	int l, idx;

	if (len <= 0) return 0;	// no point

	//check for auto receiving #help
	for (idx = 0; idx < len; idx++)
	{
		if (!is_color (text_to_add[idx])) break;
	}
	l = len - idx;
	if (l >= strlen(help_request_str) && text_to_add[idx] == '#' && (strncasecmp (&text_to_add[idx], help_request_str, strlen(help_request_str)) == 0 || strncasecmp (&text_to_add[idx], "#mod chat", 9) == 0))
	{
		auto_open_encyclopedia = 0;
	}

	/*
	DANGER, WILL ROBINSON!

	The below code should not exist in it's present form.  I'd change it,
	but I'd need access to the server.  Simply checking text output (which
	is used for all sorts of things) for the phrase "Game Date" is very
	dangerous.  Example: what if, in the future, we allow spaces in
	character names?  Someone chooses the name "Game Date" and walks around
	saying "hi".  Everyone's clients in the area interpret this as being a
	Game Date command.

	I've made the below code not *as* dangerous. Had a user been able to
	fake out the below code, previously, it would have caused a buffer overflow
	in their client if they didn't write in only numbers after it.  Now, they
	won't crash; it'll just be misparsed.

	General practice recommendation: don't mix server commands with user
	input.

	 - Karen
	*/
	/*
	ed (ttlanhil): made it check if it's a server colour. still not perfect
	(this should have been done server-side instead of parsing the date), but safer
	*/
	if (from_color_char (text_to_add[0]) == c_green1 && my_strncompare(text_to_add+1,"Game Date", 9))
	{
		//we assume that the server will still send little-endian dd/mm/yyyy... we could make it safer by parsing the format too, but it's simpler to assume
		const char * const month_names[] = { "Aluwia", "Seedar", "Akbar", "Zartia", "Elandra", "Viasia", "Fruitfall", "Mortia", "Carnelar", "Nimlos", "Chimar", "Vespia" };
		const char * const day_names[] = { "1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th", "20th", "21st", "22nd", "23rd", "24th", "25th", "26th", "27th", "28th", "29th", "30th" };
		char new_str[100];
		const char *ptr=text_to_add;
		short unsigned int day=1, month=1, year=0;
		int offset = 0;

		while(!isdigit(ptr[offset]))
		{
			offset++;
			if (offset >= sizeof(new_str))
			{
				LOG_ERROR("error (1) parsing date string: %s",text_to_add);
				//something evil this way comes...
				return 0;
			}
		}
		ptr += offset;

		if (sscanf (ptr,"%hu%*[-/]%hu%*[-/]%hu",&day,&month,&year) < 3
		    || day <= 0 || month <= 0
		    || day > 30 || month > 12 || year > 9999)
		{
			LOG_ERROR("error (2) parsing date string: %s",text_to_add);
			//something evil this way comes...
		}
		else
		{
			// only display initial or "#date" user requested date
			if (!set_date(ptr))
			{
				safe_snprintf(new_str, sizeof(new_str), date_format, day_names[day-1], month_names[month-1], year);
				LOG_TO_CONSOLE(c_green1, new_str);
			}

			//Calculate fraction Big Lunar month (2 conjunction months) less game clock time
			//Represented in Degrees.
			skybox_time_d = (SDL_GetTicks()%( 1296000 * 1000 ));
			skybox_time_d *= 360.0/( 1296000.0 * 1000.0);
			skybox_time_d = -skybox_time_d;
			skybox_time_d += 360.0 * (((month%2)*30 + day-1)*360 + game_minute)/21600.0;
			skybox_update_positions();
			return 0;
		}
	}

	if (from_color_char (text_to_add[0]) == c_green1 && my_strncompare(text_to_add+1,"Game Time", 9))
	{
		real_game_second = atoi(&text_to_add[18]);
		next_second_time = cur_time + 1000;
        new_second();
	}

	// Check for local messages to be translated into actor movements (contains [somthing])
	if (channel == CHAT_LOCAL)
	{
		if(parse_text_for_emote_commands(text_to_add, len)) return 0;
	}

	if (channel == CHAT_SERVER) {
		if (my_strncompare(text_to_add+1, "You started to harvest ", 23)) {
			strncpy(harvest_name, text_to_add+1+23, len-1-23-1);
			harvest_name[len-1-23-1] = '\0';
			harvesting = 1;
		}
		else if ((my_strncompare(text_to_add+1, "You stopped harvesting.", 23)) ||
			(my_strncompare(text_to_add+1, "You can't harvest while fighting (duh)!", 39)) ||
			(my_strncompare(text_to_add+1, "You can't do that while trading!", 32)) ||
			(my_strncompare(text_to_add+1, "You are too far away! Get closer!", 33)) ||
			(my_strncompare(text_to_add+1, "You can't harvest here", 22)) ||
			(my_strncompare(text_to_add+1, "You lack the knowledge of ", 26)) ||
			((my_strncompare(text_to_add+1, "You need to wear ", 17) && strstr(text_to_add, "order to harvest") != NULL)) ||
			((my_strncompare(text_to_add+1, "You need to have a ", 19) && strstr(text_to_add, "order to harvest") != NULL)))
		{
			harvesting = 0;
		}
		else if (is_death_message(text_to_add+1)) {
			// nothing to be done here cause all is done in the test function
		}
		else if (my_strncompare(text_to_add+1, "You found ", 10) && strstr(text_to_add+1, " coins.")) {
			decrement_harvest_counter(atoi(text_to_add+11));
		} 
		else if (my_strncompare(text_to_add+1, "Send Item UIDs ", 15)) {
			if (text_to_add[1+15] == '0')
				item_uid_enabled = 0;
			else if (text_to_add[1+15] == '1')
				item_uid_enabled = 1;
			printf("item_uid_enabled=%d\n", item_uid_enabled);
		}
		else if ((copy_next_LOCATE_ME > 0) && my_strncompare(text_to_add+1, "You are in ", 11)) {
			char buffer[4096];
			switch (copy_next_LOCATE_ME)
			{
				case 1:
					copy_to_clipboard(text_to_add+1);
					break;
				case 2:
					snprintf(buffer, sizeof(buffer), "@My Position: %s", text_to_add + 12);
					send_input_text_line(buffer, strlen(buffer));
					break;
			}
			copy_next_LOCATE_ME = 0;
			return 0;
		}
		else if (my_strncompare(text_to_add+1, "You see: ", 9)) {
			achievements_player_name(text_to_add+10, len-10);
		}
		else if (my_strncompare(text_to_add+1, "You just got food poisoned!", 27)) {
			increment_poison_incidence();
		}
		else if (strstr(text_to_add+1, "aborted the trade.")) {
			trade_aborted(text_to_add+1);
		}
		else if (strstr(text_to_add+1, "Trade session failed")) {
			trade_aborted(text_to_add+1);
		}
		else if (strstr(text_to_add+1, "You have been saved!")) {
			last_save_time = time(NULL);
		}
		
	} else if (channel == CHAT_LOCAL) {
		if (harvesting && my_strncompare(text_to_add+1, username_str, strlen(username_str))) {
			char *ptr = text_to_add+1+strlen(username_str);
			if (my_strncompare(ptr, " found a ", 9)) {
				ptr += 9;
				if (my_strncompare(ptr, "bag of gold, getting ", 21)) {
					decrement_harvest_counter(atoi(ptr+21));
				} else if (!strstr(ptr, " could not carry ")) {
					decrement_harvest_counter(1);
				}
			}
		} else if (my_strncompare(text_to_add+1, "(*) ", 4)) {
			increment_summon_counter(text_to_add+1+4);
			if (summoning_filter) return 0;
		}
	}
	/* check for misc counter strings */
	catch_counters_text(text_to_add+1);

	/* put #mpm in a popup box, on top of all else */
	if ((channel == CHAT_MODPM) && (my_strncompare(text_to_add+1, "[Mod PM from", 12))) {
		display_server_popup_win(text_to_add);
	}

	//Make sure we don't check our own messages.
	if( !(channel == CHAT_PERSONAL && len >= strlen(pm_from_str) && strncasecmp (text_to_add+1, pm_from_str, strlen(pm_from_str)) != 0) &&
		!(channel == CHAT_MODPM && len >= strlen(mod_pm_from_str) && strncasecmp (text_to_add+1, mod_pm_from_str, strlen(mod_pm_from_str)) != 0)
	) {

		//check if ignored - pre_check_if_ignored() checks for Mod PM's etc to not ignore (or it  would be asking for trouble)
		if (pre_check_if_ignored (text_to_add, len, channel))
		{
			return 0;
		}
		//All right, we do not ignore the person
		if (afk)
		{
			if (channel == CHAT_PERSONAL || channel == CHAT_MODPM)
			{
				// player sent us a PM
				add_message_to_pm_log (text_to_add, len, channel);
				if (afk_snd_warning) {
					do_afk_sound();
				}
			}
			else if (channel == CHAT_LOCAL && from_color_char (text_to_add[0]) == c_grey1 && is_talking_about_me (&text_to_add[1], len-1, 0))
			{
				// player mentions our name in local chat
				if (afk_local) {
					add_message_to_pm_log (&text_to_add[1], len - 1, channel);
					if (afk_snd_warning) {
						do_afk_sound();
					}
				} else {
					send_afk_message (&text_to_add[1], len - 1, channel);
				}
			}
			else if (channel == CHAT_SERVER)
			{
				// check if this was a trade attempt
				int i;
				for (i = 1; i < len; i++) {
					if (text_to_add[i] == ' ' || text_to_add[i] == ':' || is_color (text_to_add[i])) {
						break;
					}
				}
				if (i < len-15 && strncasecmp (&text_to_add[i], " wants to trade", 15) == 0) {
					send_afk_message (&text_to_add[1], len - 1, channel);
					if (afk_snd_warning) {
						do_afk_sound();
					}
				}
			}
		}
	} else {	//We sent this PM or MODPM. Can we expect a reply?
		int len = 0;
		char name[MAX_USERNAME_LENGTH];
		for(;text_to_add[len+8] != ':' && len < MAX_USERNAME_LENGTH - 1; ++len);
		safe_strncpy(name, text_to_add+8, len+1);
		if(check_if_ignored(name)){
			char msg[65];
			safe_snprintf(msg, sizeof(msg), warn_currently_ignoring, name);
			LOG_TO_CONSOLE(c_red2, msg);
		}
	}

	// parse for URLs
	find_all_url (text_to_add, len);

	// look for buddy-wants-to-add-you messages
	if(channel == CHAT_SERVER && from_color_char (text_to_add[0]) == c_green1)
	{
		for (l = 1; l < len; l++)
		{
			if (text_to_add[l] == ' ') break;
		}
		if (len - l >= strlen(msg_accept_buddy_str) && strncmp (&text_to_add[l], msg_accept_buddy_str, strlen(msg_accept_buddy_str)) == 0 && l <=32)
		{
			char name[32];
			int i;
			int cur_char;
			/*entropy says: I really fail to understand the logic of that safe_snprintf. And gcc can't understand it either
			  because the name is corrupted. so we implement it the old fashioned way.
			  Grum responds: actually it's the MingW compiler on windows that doesn't understand it, because it doesn't
			  terminate the string when the buffer threatens to overflow. It works fine with gcc on Unix, and using
			  sane_safe_snprintf should also fix it on windows.
			safe_snprintf (name, l, "%s", &text_to_add[1]);
			*/
			for (i = 0; i < sizeof (name); i++)
			{
				cur_char = text_to_add[i+1];
				name[i] = cur_char;
				if (cur_char == ' ')
				{
					name[i] = '\0';
					break;
				}
			}
			add_buddy_confirmation (name);
		}
	}

	// look for astrology messages
	if((channel == CHAT_SERVER) && is_astrology_message (text_to_add))
	{
		return 0;
	}

	// filter any naughty words out
	return filter_text (text_to_add, len, size);
}
예제 #12
0
int parse_text_for_emote_commands(const char *text, int len)
{
	int i=0, j = 0, wf=0,ef=0, itsme=0;
	char name[20];	// Yeah, this should be done correctly
	emote_dict emote_text;
	actor *act;

	
	//printf("parsing local for emotes\n");
	//extract name
	while(text[i]&&i<20){
		if (is_color(text[i])) {i++; continue;}
		name[j]=text[i];
		if(text[i]==' ' || text[i]==':') {
			name[j]=0;
			if(text[i]==':') i++;
			break;
		} 
		i++;j++;
	}

	if(j>=20||name[j]) return 0; 		//out of bound or not terminated

	//check if we are saying text
	LOCK_ACTORS_LISTS();

	act = get_actor_ptr_from_id(yourself);
	if (!act){
		UNLOCK_ACTORS_LISTS();
		LOG_ERROR("Unable to find actor who just said local text?? name: %s", name);
		return 1;		// Eek! We don't have an actor match... o.O
	}

	if (!(!strncasecmp(act->actor_name, name, strlen(name)) && 
			(act->actor_name[strlen(name)] == ' ' ||
			act->actor_name[strlen(name)] == '\0'))){
		//we are not saying this text, return
		//UNLOCK_ACTORS_LISTS();			
		//return 0;
			itsme=0;
	} else itsme=1;

	j=0;
	do {
		if (is_color(text[i])) continue;
		if ((text[i]==' ' || text[i]==0)) {
			if (j&&j<=MAX_EMOTE_LEN) {
				wf++;
				emote_text.command[j]=0;
				ef+=match_emote(&emote_text,act,itsme);
			} else wf+= (j) ? 1:0;
			j=0;
		} else {
			if (j<MAX_EMOTE_LEN)
				emote_text.command[j]=text[i];
			j++;
		}
	} while(text[i++]);	
	//printf("ef=%i, wf=%i, filter=>%i\n",ef,wf,emote_filter);
	UNLOCK_ACTORS_LISTS();			

	return  ((ef==wf) ? (emote_filter):(0));

}
예제 #13
0
void write_to_log (Uint8 channel, const Uint8* const data, int len)
{
	int i, j;
	Uint8 ch;
	char str[1024];
	struct tm *l_time; time_t c_time;
	FILE *fout;

#ifdef NEW_SOUND
	// Check if this string matches text we play a sound for
	check_sound_alerts(data, len, channel);
#endif // NEW_SOUND

	if(log_chat == LOG_NONE || (channel == CHAT_SERVER && log_chat == LOG_CHAT))
		// We're not logging at all, or this is a server message and
		// we're not logging those
		return;

	if (chat_log == NULL){
		open_chat_log();
		if(chat_log == NULL){
			return;
		}
	}

	// The file we'll write to
	fout = (channel == CHAT_SERVER && log_chat >= 3) ? srv_log : chat_log;

	if(!show_timestamp)
	{
		// Start filling the buffer with the time stamp
		time (&c_time);
		l_time = localtime (&c_time);
		j = strftime (str, sizeof(str), "[%H:%M:%S] ", l_time);
	}
	else
	{
		//we already have a time stamp
		j=0;
	}

	i = 0;
	while (i < len)
	{
		for ( ; i < len && j < sizeof (str) - 1; i++)
		{
			ch = data[i];

			// remove colorization and soft wrapping characters when
			// writing to the chat log
			if (!is_color (ch) && ch != '\r')
				str[j++] = ch;
		}
		if (i >= len) str[j++]='\n';

		fwrite (str, j, 1, fout);

		// start again at the beginning of the buffer
		j = 0;
	}

	// Flush the file, so the content is written even when EL crashes.
	fflush (fout);
}
예제 #14
0
void put_small_colored_text_in_box (Uint8 color, const Uint8 *text_to_add, int len, int pixels_limit, char *buffer)
{
	int i;
	Uint8 cur_char;
	int last_text = 0;
	int x_chars_limit;

	// force the color
	if (!is_color (text_to_add[0]))
		buffer[last_text++] = to_color_char (color);

	//see if the text fits on the screen
	x_chars_limit = pixels_limit / 8;
	if (len <= x_chars_limit)
	{
		for (i = 0; i < len; i++)
		{
			cur_char = text_to_add[i];

			if (cur_char == '\0')
				break;

			buffer[last_text++] = cur_char;
		}
		if (last_text > 0 && buffer[last_text-1] != '\n')
			buffer[last_text++] = '\n';
		buffer[last_text] = '\0';
	}
	else //we have to add new lines to our text...
	{
		int k;
		int new_line_pos = 0;
		char semaphore = 0;
		Uint8 current_color = to_color_char (color);

		// go trought all the text
		for (i = 0; i < len; i++)
		{
			if (!semaphore && new_line_pos + x_chars_limit < len) //don't go through the last line
			{
				//find the closest space from the end of this line
				//if we have one really big word, then parse the string from the
				//end of the line backwards, untill the beginning of the line +2
				//the +2 is so we avoid parsing the ": " thing...
				for (k = new_line_pos + x_chars_limit - 1; k > new_line_pos + 2; k--)
				{
					cur_char = text_to_add[k];
					if (k > len) continue;
					if (cur_char == ' ' || cur_char == '\n')
					{
						k++; // let the space on the previous line
						break;
					}
				}
				if (k == new_line_pos + 2)
					new_line_pos += x_chars_limit;
				else
					new_line_pos = k;
				semaphore = 1;
			}

			cur_char = text_to_add[i];
			if (cur_char == '\0') break;

			if (is_color (cur_char)) // we have a color, save it
			{
				current_color = cur_char;
				if (last_text > 0 && is_color (buffer[last_text-1]))
					last_text--;
			}
			else if (cur_char == '\n')
			{
				new_line_pos = i;
			}

			if (i == new_line_pos)
			{
				buffer[last_text++] = '\n';
				// don't add color codes after the last newline
				if (i < len-1)
					buffer[last_text++] = current_color;
				semaphore = 0;
			}
			//don't add another new line, if the current char is already a new line...
			if (cur_char != '\n')
				buffer[last_text++] = cur_char;

		}
		// don't add extra newlines if there already is one
		if (last_text > 0 && buffer[last_text-1] != '\n')
			buffer[last_text++] = '\n';
		buffer[last_text] = '\0';
	}
}
예제 #15
0
//returns the new length of the text
int filter_text (char *buff, int len, int size)
{
	int i, t, bad_len, rep_len, new_len, idx;

	if (len > 31 && my_strncompare (buff+1, "Items you have in your storage:", 31)){
		//First up, attempt to save the storage list for re-reading later
		if(size <= sizeof(cached_storage_list)){
			memcpy(cached_storage_list, buff, size);
			have_storage_list = 1;
		}
		// See if a search term has been added to the #storage command, and if so, 
		//only list those items with that term
		if (storage_filter[0] != '\0'){
			len = 33 + filter_storage_text (buff+33, len-33, size-33);
		}
	}

	//do we need to do CAPS filtering?
	if (caps_filter)
	{ 
		int idx, clen = len;

		// skip any coloring
		idx = 0;
		while (is_color (buff[idx]) && clen > 0)
		{
			idx++;
			clen--;
		}

		// handle PM's
		if (buff[idx] == '[' || buff[idx+1] == '[')
		{
			while (buff[idx] != '\0' && buff[idx] != ':' && clen > 0)
			{
				idx++;
				clen--;
			}
		}
		// or ignore first word
		else
		{
			while (buff[idx] != '\0' && buff[idx] != ' ' && buff[idx] != ':' && clen > 0)
			{
				idx++;
				clen--;
			}
		}
		
		while (buff[idx] != '\0' && (buff[idx] == ' ' || buff[idx] == ':' || is_color (buff[idx])) && clen > 0)
		{
			idx++;
			clen--;
		}
		
		// check for hitting the EOS
		if (buff[idx] == '\0') idx = 0;
		// if we pass the upper test, entire line goes lower
		if (len - idx > 4 && my_isupper (&buff[idx], clen))
		{
			// don't call my_tolower, since we're not sure if the string is NULL terminated
			for (idx = 0; idx < len; idx++)
				buff[idx] = tolower (buff[idx]);
		}
	}
	
	//do we need to do any content filtering?
	if (filtered_so_far == 0) return len;

	// scan the text for any strings
	new_len = len;
	i = 0;
	while (i < new_len)
	{
		/* skip non-alpha characters */
		while (i < new_len && !isalpha ((unsigned char)buff[i])) i++;
		if (i >= new_len) break;
		
		/* check if we need to filter this word */
		idx = check_if_filtered (&buff[i]);
		if (idx >= 0)
		{
			/* oops, remove this word */
			if (filter_list[idx].wildcard_type > 0)
			{
				bad_len = 0;
				for (t = 0; ; t++)
				{
					if (!isalpha (buff[i+t])) break;
					bad_len++;
				}
			}
			else
			{
				bad_len = filter_list[idx].len;
			}
			rep_len = filter_list[idx].rlen;

			if (bad_len == rep_len)
			{
				memcpy(buff+i, filter_list[idx].replacement, rep_len);
			}
			else if (new_len + rep_len - bad_len >= size - 1)
			{
				// not enough space for substitution
				break;
			}
			else
			{
				memmove(buff+i+rep_len, buff+i+bad_len, new_len-i-bad_len+1);
				memcpy(buff+i, filter_list[idx].replacement, rep_len);
				new_len+= rep_len - bad_len;
			}
			/* don't filter the replacement text */
			i += rep_len;
		}
		else
		{
			/* skip this word */
			while (i < new_len && isalpha (buff[i])) i++;
		}
	}
	
	return new_len;
}
예제 #16
0
static __inline__ void draw_actor_points(float zoom_multip, float px, float py)
{
	float size_x = float_minimap_size / (tile_map_size_x * 6);
	float size_y = float_minimap_size / (tile_map_size_y * 6);
	actor *a;
	int i;
	float x, y;

	glPushMatrix();
	glDisable(GL_TEXTURE_2D);

	//display the actors
	glEnable( GL_POINT_SMOOTH );
	glEnable( GL_BLEND );
	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
	glPointSize(8);

	rotate_actor_points(zoom_multip,px,py);

	glBegin(GL_POINTS);

	for (i = 0; i < max_actors; i++)
	{
		if (actors_list[i])
		{
			a = actors_list[i];
			if (a->attached_actor != -1 && a->actor_id == -1)
				continue;
			x = a->x_tile_pos * size_x;
			y = float_minimap_size - (a->y_tile_pos * size_y);

			glColor3f(0.0f,0.0f,0.0f);
			glVertex2f(x+2*zoom_multip, y+2*zoom_multip);

			if (a->kind_of_actor == NPC)
				elglColourN("minimap.npc");
			else if(a->actor_id == yourself)
				elglColourN("minimap.yourself");
			else if(a->is_enhanced_model && (a->kind_of_actor ==  PKABLE_HUMAN || a->kind_of_actor == PKABLE_COMPUTER_CONTROLLED))
				elglColourN("minimap.pkable");
			else if(a->is_enhanced_model && is_in_buddylist(a->actor_name))
				elglColourN("minimap.buddy");
			else if (is_color ((unsigned char)a->actor_name[0]))
			{
				if(a->is_enhanced_model && is_in_buddylist(a->actor_name))
					elglColourN("minimap.buddy");
				else
				{	// Use the colour of their name. This gives purple bots, green demigods, etc.
					int color = from_color_char (a->actor_name[0]);
					glColor3ub (colors_list[color].r1,
						colors_list[color].g1,
						colors_list[color].b1);
				}
			}
			else if(!a->is_enhanced_model)
			{
				if (a->dead) 
					elglColourN("minimap.deadcreature");
				else // alive
					elglColourN("minimap.creature");
			}
			else
				elglColourN("minimap.otherplayer");
			// Draw it!
			glVertex2f(x, y);
		}
	}
	
	// mines
	for (i = 0; i < NUM_MINES; i++)
	{
		mine *m = &mine_list[i];
		if (m->obj_3d_id != -1)
		{
			x = m->x * size_x;
			y = float_minimap_size - (m->y * size_y);
			if(is_within_radius(x,y,px,py,zoom_multip*(minimap_size/2-15)))
			{
				elglColourN("minimap.mine");
				glVertex2f(x, y);
			}
		}
	}

	glEnd();//GL_POINTS
	glDisable(GL_BLEND);
	glDisable(GL_POINT_SMOOTH);

	glPopMatrix();
	
	if (pf_follow_path)
	{
		x = pf_dst_tile->x * size_x;
		y = float_minimap_size - (pf_dst_tile->y * size_y);

		if (x != px || y != py)
		{
			float diff = 6.0f*zoom_multip;

			if(is_within_radius(x,y,px,py,zoom_multip*(minimap_size/2-15)))
			{
				glPushMatrix();
				glDisable(GL_TEXTURE_2D);
				rotate_actor_points(zoom_multip,px,py);
				glBegin(GL_LINES);
				glColor3f(1.0f,0.0f,1.0f); //purple
				glVertex2f(x-diff, y-diff);
				glVertex2f(x+diff, y+diff);
				glVertex2f(x-diff, y+diff);
				glVertex2f(x+diff, y-diff);
				glEnd();//GL_LINES
				glPopMatrix();
			}
		}
	}

	//draw map markings
	for(i=0;i<max_mark;i++){
		if(!marks[i].server_side) continue;
		x= marks[i].x*size_x;
		y= float_minimap_size-(marks[i].y*size_y);
		if (x != px || y != py)
		{
			float diff = 4.0f*zoom_multip;
	
			if(is_within_radius(x,y,px,py,zoom_multip*(minimap_size/2-15)))
			{
				glPushMatrix();
				glDisable(GL_TEXTURE_2D);
				rotate_actor_points(zoom_multip,px,py);
				glBegin(GL_LINES);
				elglColourN("minimap.servermark");
				glVertex2f(x-diff, y-diff);
				glVertex2f(x+diff, y+diff);
				glVertex2f(x-diff, y+diff);
				glVertex2f(x+diff, y-diff);
				glEnd();//GL_LINES
				glPopMatrix();
			}
		}
	}


	glColor4f(1.0f,1.0f,1.0f,1.0f);
	glEnable(GL_TEXTURE_2D);
}
예제 #17
0
void draw_ortho_ingame_string(float x, float y,float z, const unsigned char * our_string,
						int max_lines, float font_x_scale, float font_y_scale)
{
	float u_start,u_end,v_start,v_end;
	int col,row;
	float displayed_font_x_size;
	float displayed_font_y_size;

	float displayed_font_x_width;
#ifndef SKY_FPV_OPTIONAL
	int font_x_size=FONT_X_SPACING;
	int font_y_size=FONT_Y_SPACING;
#endif // not SKY_FPV_OPTIONAL
	int	font_bit_width, ignored_bits;

	unsigned char cur_char;
	int chr;
	int i;
	float cur_x,cur_y;
	int current_lines=0;

#ifndef SKY_FPV_OPTIONAL
	/*
	if(big)
		{
			displayed_font_x_size=0.17*zoom_level*name_zoom/3.0;
			displayed_font_y_size=0.25*zoom_level*name_zoom/3.0;
		}
	else
		{
			displayed_font_x_size=SMALL_INGAME_FONT_X_LEN*zoom_level*name_zoom/3.0;
			displayed_font_y_size=SMALL_INGAME_FONT_Y_LEN*zoom_level*name_zoom/3.0;
		}
	*/
#endif // not SKY_FPV_OPTIONAL
	displayed_font_x_size=font_x_scale*name_zoom*12.0;
	displayed_font_y_size=font_y_scale*name_zoom*12.0;

	glEnable(GL_ALPHA_TEST);//enable alpha filtering, so we have some alpha key
	glAlphaFunc(GL_GREATER,0.1f);
#ifdef	NEW_TEXTURES
	bind_texture(font_text);
#else	/* NEW_TEXTURES */
	get_and_set_texture_id(font_text);
#endif	/* NEW_TEXTURES */

	i=0;
	cur_x=x;
	cur_y=y;
	glBegin(GL_QUADS);
#ifndef SKY_FPV_OPTIONAL
	while(1)
		{
			cur_char=our_string[i];
			if(!cur_char)
				{
					break;
				}
			else if(cur_char=='\n')
				{
					cur_y+=displayed_font_y_size;
					cur_x=x;
					i++;
					current_lines++;
					if(current_lines>=max_lines)break;
					continue;
				}
			else if (is_color (cur_char))
				{
					glEnd();	//Ooops - NV bug fix!!
				}
			chr=find_font_char(cur_char);
			if(chr >= 0)
				{
					col=chr/FONT_CHARS_PER_LINE;
					row=chr%FONT_CHARS_PER_LINE;


					font_bit_width=get_font_width(chr);
					displayed_font_x_width=((float)font_bit_width)*displayed_font_x_size/12.0;
					ignored_bits=(12-font_bit_width)/2;	// how many bits on each side of the char are ignored?
					if(ignored_bits < 0)ignored_bits=0;

					//now get the texture coordinates
					u_start=(float)(row*font_x_size+ignored_bits)/256.0f;
					u_end=(float)(row*font_x_size+font_x_size-7-ignored_bits)/256.0f;
#ifdef NEW_TEXTURES
					v_start=(float)(1+col*font_y_size)/256.0f;
					v_end=(float)(col*font_y_size+font_y_size-1)/256.0f;
#else
					v_start=(float)1.0f-(1+col*font_y_size)/256.0f;
					v_end=(float)1.0f-(col*font_y_size+font_y_size-1)/256.0f;
#endif //NEW_TEXTURES
					//v_end=(float)1.0f-(col*font_y_size+font_y_size-2)/256.0f;

					glTexCoord2f(u_start,v_start);
					glVertex3f(cur_x,cur_y+displayed_font_y_size,z);

					glTexCoord2f(u_start,v_end);
					glVertex3f(cur_x,cur_y,z);

					glTexCoord2f(u_end,v_end);
					glVertex3f(cur_x+displayed_font_x_width,cur_y,z);

					glTexCoord2f(u_end,v_start);
					glVertex3f(cur_x+displayed_font_x_width,cur_y+displayed_font_y_size,z);


					//cur_x+=displayed_font_x_size;
					cur_x+=displayed_font_x_width;
				}
			else if (is_color (cur_char))
				{
					glBegin(GL_QUADS);	//Ooops - NV bug fix!!
				}

#else // SKY_FPV_OPTIONAL
	while(1){
		cur_char=our_string[i];
		if(!cur_char){
			break;
		} else if(cur_char=='\n'){
			cur_y+=displayed_font_y_size;
			cur_x=x;
#endif // SKY_FPV_OPTIONAL
			i++;
#ifdef SKY_FPV_OPTIONAL
			current_lines++;
			if(current_lines>=max_lines)break;
			continue;
		} else if (is_color (cur_char)){
			glEnd();	//Ooops - NV bug fix!!
			glBegin(GL_QUADS);
		}
		chr=find_font_char(cur_char);
		if(chr >= 0){
			col=chr/FONT_CHARS_PER_LINE;
			row=chr%FONT_CHARS_PER_LINE;

			font_bit_width=get_font_width(chr);
			displayed_font_x_width=((float)font_bit_width)*displayed_font_x_size/12.0;
			ignored_bits=(12-font_bit_width)/2;	// how many bits on each side of the char are ignored?
			if(ignored_bits < 0)ignored_bits=0;

			//now get the texture coordinates
			u_start=(float)(row*FONT_X_SPACING+ignored_bits)/256.0f;
			u_end=(float)(row*FONT_X_SPACING+FONT_X_SPACING-7-ignored_bits)/256.0f;
#ifdef NEW_TEXTURES
			v_start=(float)(1+col*FONT_Y_SPACING)/256.0f;
			v_end=(float)(col*FONT_Y_SPACING+FONT_Y_SPACING-1)/256.0f;
#else
			v_start=(float)1.0f-(1+col*FONT_Y_SPACING)/256.0f;
			v_end=(float)1.0f-(col*FONT_Y_SPACING+FONT_Y_SPACING-1)/256.0f;
#endif //NEW_TEXTURES

			glTexCoord2f(u_start,v_start);
			glVertex3f(cur_x,cur_y+displayed_font_y_size,z);

			glTexCoord2f(u_start,v_end);
			glVertex3f(cur_x,cur_y,z);

			glTexCoord2f(u_end,v_end);
			glVertex3f(cur_x+displayed_font_x_width,cur_y,z);

			glTexCoord2f(u_end,v_start);
			glVertex3f(cur_x+displayed_font_x_width,cur_y+displayed_font_y_size,z);

			cur_x+=displayed_font_x_width;
		} else if(is_color (cur_char)){
			glEnd();	//Ooops - NV bug fix!!
			glBegin(GL_QUADS);
#endif // SKY_FPV_OPTIONAL
		}
#ifdef SKY_FPV_OPTIONAL
	i++;
	}
#endif // SKY_FPV_OPTIONAL

	glEnd();
	glDisable(GL_ALPHA_TEST);
}

void draw_ingame_string(float x, float y,const unsigned char * our_string,
						int max_lines, float font_x_scale, float font_y_scale)
{
	float u_start,u_end,v_start,v_end;
	int col,row;
	float displayed_font_x_size;
	float displayed_font_y_size;

	float displayed_font_x_width;
#ifndef SKY_FPV_OPTIONAL
	//int font_x_size=FONT_X_SPACING;
	//int font_y_size=FONT_Y_SPACING;
#endif // not SKY_FPV_OPTIONAL
	int	font_bit_width, ignored_bits;

	unsigned char cur_char;
	int chr;
	int i;
	float cur_x,cur_y;
	int current_lines=0;
#ifdef SKY_FPV_OPTIONAL
	double model[16], proj[16],hx,hy,hz;
	int view[4];

	displayed_font_x_size=font_x_scale*name_zoom*12.0*font_scale;
	displayed_font_y_size=font_y_scale*name_zoom*12.0*font_scale;

	glGetDoublev(GL_MODELVIEW_MATRIX, model);
	glGetDoublev(GL_PROJECTION_MATRIX, proj);
	glGetIntegerv(GL_VIEWPORT, view);
	gluProject((double)x,0.0f,(double)y,model, proj, view, &hx,&hy,&hz);
	glPushMatrix();
	glLoadIdentity();
	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	glOrtho(view[0],view[2]+view[0],view[1],view[3]+view[1],0.0f,-1.0f);
#endif // SKY_FPV_OPTIONAL

#ifndef SKY_FPV_OPTIONAL
	displayed_font_x_size=font_x_scale*zoom_level*name_zoom/3.0;
	displayed_font_y_size=font_y_scale*zoom_level*name_zoom/3.0;
#endif // not SKY_FPV_OPTIONAL

	glEnable(GL_ALPHA_TEST);//enable alpha filtering, so we have some alpha key
	glAlphaFunc(GL_GREATER,0.1f);
#ifdef	NEW_TEXTURES
	bind_texture(font_text);
#else	/* NEW_TEXTURES */
	get_and_set_texture_id(font_text);
#endif	/* NEW_TEXTURES */

	i=0;
#ifndef SKY_FPV_OPTIONAL
	cur_x=x;
	cur_y=y;
#else // SKY_FPV_OPTIONAL
	cur_x=hx;
	cur_y=hy;
#endif // SKY_FPV_OPTIONAL
	glBegin(GL_QUADS);
#ifndef SKY_FPV_OPTIONAL
	while(1)
		{
			cur_char=our_string[i];
			if(!cur_char)
				{
					break;
				}
			else if(cur_char=='\n')
				{
					cur_y+=displayed_font_y_size;
					cur_x=x;
					i++;
					current_lines++;
					if(current_lines>=max_lines)break;
					continue;
				}
			else if(is_color (cur_char))
				{
					glEnd();	//Ooops - NV bug fix!!
				}
			chr=find_font_char(cur_char);
			if(chr >= 0)
				{
					col=chr/FONT_CHARS_PER_LINE;
					row=chr%FONT_CHARS_PER_LINE;

					font_bit_width=get_font_width(chr);
					displayed_font_x_width=((float)font_bit_width)*displayed_font_x_size/12.0;
					ignored_bits=(12-font_bit_width)/2;	// how many bits on each side of the char are ignored?
					if(ignored_bits < 0)ignored_bits=0;

					//now get the texture coordinates
					u_start=(float)(row*FONT_X_SPACING+ignored_bits)/256.0f;
					u_end=(float)(row*FONT_X_SPACING+FONT_X_SPACING-7-ignored_bits)/256.0f;
#ifdef NEW_TEXTURES
					v_start=(float)(1+col*FONT_Y_SPACING)/256.0f;
					v_end=(float)(col*FONT_Y_SPACING+FONT_Y_SPACING-1)/256.0f;
#else
					v_start=(float)1.0f-(1+col*FONT_Y_SPACING)/256.0f;
					v_end=(float)1.0f-(col*FONT_Y_SPACING+FONT_Y_SPACING-1)/256.0f;
#endif //NEW_TEXTURES

					glTexCoord2f(u_start,v_start);
					glVertex3f(cur_x,0,cur_y+displayed_font_y_size);

					glTexCoord2f(u_start,v_end);
					glVertex3f(cur_x,0,cur_y);

					glTexCoord2f(u_end,v_end);
					glVertex3f(cur_x+displayed_font_x_width,0,cur_y);

					glTexCoord2f(u_end,v_start);
					glVertex3f(cur_x+displayed_font_x_width,0,cur_y+displayed_font_y_size);

					cur_x+=displayed_font_x_width;
				}
			else if (is_color (cur_char))
				{
					glBegin(GL_QUADS);	//Ooops - NV bug fix!!
				}
#else // SKY_FPV_OPTIONAL
	while(1){
		cur_char=our_string[i];
		if(!cur_char){
			break;
		}else if(cur_char=='\n'){
			cur_y+=displayed_font_y_size;
			cur_x=hx;
#endif // SKY_FPV_OPTIONAL
			i++;
#ifdef SKY_FPV_OPTIONAL
			current_lines++;
			if(current_lines>=max_lines)break;
			continue;
		}
		else if (is_color (cur_char))
		{
			glEnd();	//Ooops - NV bug fix!!
			glBegin(GL_QUADS);
		}
		chr=find_font_char(cur_char);
		if(chr >= 0){
			col=chr/FONT_CHARS_PER_LINE;
			row=chr%FONT_CHARS_PER_LINE;

			font_bit_width=get_font_width(chr);
			displayed_font_x_width=((float)font_bit_width)*displayed_font_x_size/12.0;
			ignored_bits=(12-font_bit_width)/2;	// how many bits on each side of the char are ignored?
			if(ignored_bits < 0)ignored_bits=0;

			//now get the texture coordinates
			u_start=(float)(row*FONT_X_SPACING+ignored_bits)/256.0f;
			u_end=(float)(row*FONT_X_SPACING+FONT_X_SPACING-7-ignored_bits)/256.0f;
#ifdef NEW_TEXTURES
			v_start=(float)(1+col*FONT_Y_SPACING)/256.0f;
			v_end=(float)(col*FONT_Y_SPACING+FONT_Y_SPACING-1)/256.0f;
#else
			v_start=(float)1.0f-(1+col*FONT_Y_SPACING)/256.0f;
			v_end=(float)1.0f-(col*FONT_Y_SPACING+FONT_Y_SPACING-1)/256.0f;
#endif // NEW_TEXTURES

			glTexCoord2f(u_start,v_start);
			glVertex3f(cur_x,cur_y+displayed_font_y_size,0);

			glTexCoord2f(u_start,v_end);
			glVertex3f(cur_x,cur_y,0);

			glTexCoord2f(u_end,v_end);
			glVertex3f(cur_x+displayed_font_x_width,cur_y,0);

			glTexCoord2f(u_end,v_start);
			glVertex3f(cur_x+displayed_font_x_width,cur_y+displayed_font_y_size,0);

			cur_x+=displayed_font_x_width;
		}
		else if (is_color (cur_char))
		{
			glEnd();	//Ooops - NV bug fix!!
			glBegin(GL_QUADS);
#endif // SKY_FPV_OPTIONAL
		}
#ifdef SKY_FPV_OPTIONAL
		i++;
	}
#endif // SKY_FPV_OPTIONAL

	glEnd();
	glDisable(GL_ALPHA_TEST);
#ifdef SKY_FPV_OPTIONAL
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);
	glPopMatrix();

#endif // SKY_FPV_OPTIONAL
}
#endif //!MAP_EDITOR_2
#endif	//ELC



// font handling
int get_font_width(int cur_char)
{
	// ignore unknown characters
	if (cur_char < 0) {
		return 0;
	}
	// return width of character + spacing between chars (supports variable width fonts)
	return (fonts[cur_font_num]->widths[cur_char] + fonts[cur_font_num]->spacing);
}

int get_char_width(unsigned char cur_char)
{
	return get_font_width(get_font_char(cur_char));
}


int get_string_width(const unsigned char *str)
{
	return get_nstring_width(str, strlen((char*)str));
}


int get_nstring_width(const unsigned char *str, int len)
{
	int	i, wdt=0;

	for(i=0; i<len; i++) {
		wdt+= get_char_width(str[i]);
	}

	// adjust to ignore the final spacing
	wdt-= fonts[cur_font_num]->spacing;

	return wdt;
}
예제 #18
0
// Returns 1 if ignored, 0 if not ignored
int pre_check_if_ignored (const char *input_text, int len, Uint8 channel)
{
	int offset;
	char name[MAX_USERNAME_LENGTH] = {0};

	if (channel == CHAT_MODPM)
	{
		return 0;		// Don't ever ignore MOD PM's
	}
	
	switch(channel)
	{
		case CHAT_PERSONAL:
			offset = strlen(pm_from_str) + 2;
			get_name_from_text(input_text, len, 0, offset, name);		// Type 0 = ":" or " "
			break;
		case CHAT_LOCAL:
			offset = 0;
			while (is_color (input_text[offset]))
			{
				offset++;
			}
			offset += get_name_from_text(input_text, len, 1, offset, name);		// Type 1 = ":", " " or is_color
			if (!name_is_valid(name))
			{
				//This can be a lot. Let's separate them based on the color for now.
				switch (from_color_char (*input_text))
				{
					case c_grey1:
						//Check for summoning messages
						//(*) NAME summoned a %s
						if (strcmp(name, "(*)") == 0)
						{
							while (offset < len && isspace(input_text[offset]))
							{
								offset++;
							}
							get_name_from_text(input_text, len, 2, offset, name);		// Type 2 = isspace
						}
						break;
				}
			}
			break;
		case CHAT_GM:
			for (offset = 0; is_color (input_text[offset]); offset++);		// Ignore colours
			if(strncasecmp(input_text+offset, gm_from_str, strlen(gm_from_str)) == 0)
			{
				offset = strlen(gm_from_str)+2;
				get_name_from_text(input_text, len, 0, offset, name);		// Type 0 = ":" or " "
			}
			else if(strncasecmp(input_text+offset, ig_from_str, strlen(ig_from_str)) == 0)
			{
				offset = strlen(ig_from_str)+1;
				get_name_from_text(input_text, len, 4, offset, name);		// Type 4 = ":", "-" or " "
			}
			break;
		case CHAT_MOD:
			for (offset = 0; is_color (input_text[offset]); offset++);		// Ignore colours
			if(strncasecmp(input_text+offset, mc_from_str, strlen(mc_from_str)) == 0)
			{
				offset = strlen(mc_from_str)+2;
				get_name_from_text(input_text, len, 0, offset, name);		// Type 0 = ":" or " "
			}
			break;
		case CHAT_SERVER:
			for (offset = 0; is_color (input_text[offset]); offset++);		// Ignore colours
			if(strncasecmp(input_text+offset, "delayed: ", 9) == 0)
			{
				offset = 10;
				if(strncasecmp(input_text+offset, pm_from_str, strlen(pm_from_str)) == 0)
				{
					offset += strlen(pm_from_str)+1;
					get_name_from_text(input_text, len, 0, offset, name);		// Type 0 = ":" or " "
				}
			}
			break;
	}
	#if defined(OTHER_LIFE) && defined(OTHER_LIFE_EXTENDED_CHAT)
		if(loadsofchannels == 3)
		{
			switch(channel) {
				case CHAT_CHANNEL1:
				case CHAT_CHANNEL2:
				case CHAT_CHANNEL3:
					for (offset = 0; is_color (input_text[offset]); offset++);		// Ignore colours
					if (input_text[offset] == '[')
					{
						offset++;
					}
					get_name_from_text(input_text, len, 3, offset, name);		// Type 3 = ":", " " or "]"
			}
		}
		else
		{
			switch(channel) {
				case CHAT_CHANNEL1:
				case CHAT_CHANNEL2:
				case CHAT_CHANNEL3:
				case CHAT_CHANNEL4:
				case CHAT_CHANNEL5:
				case CHAT_CHANNEL6:
				case CHAT_CHANNEL7:
				case CHAT_CHANNEL8:
				case CHAT_CHANNEL9:
				case CHAT_CHANNEL10:
				case CHAT_CHANNEL11:
				case CHAT_CHANNEL12:
				case CHAT_CHANNEL13:
				case CHAT_CHANNEL14:
				case CHAT_CHANNEL15:
				case CHAT_CHANNEL16:
				case CHAT_CHANNEL17:
				case CHAT_CHANNEL18:
				case CHAT_CHANNEL19:
				case CHAT_CHANNEL20:
				case CHAT_CHANNEL21:
				case CHAT_CHANNEL22:
				case CHAT_CHANNEL23:
				case CHAT_CHANNEL24:
				case CHAT_CHANNEL25:
				case CHAT_CHANNEL26:
				case CHAT_CHANNEL27:
				case CHAT_CHANNEL28:
				case CHAT_CHANNEL29:
				case CHAT_CHANNEL30:
				case CHAT_CHANNEL31:
				case CHAT_CHANNEL32:
					for (offset = 0; is_color (input_text[offset]); offset++);		// Ignore colours
					if (input_text[offset] == '[')
					{
						offset++;
					}
					get_name_from_text(input_text, len, 3, offset, name);		// Type 3 = ":", " " or "]"
			}
		}
	#else
		switch (channel) {
			case CHAT_CHANNEL1:
			case CHAT_CHANNEL2:
			case CHAT_CHANNEL3:
				for (offset = 0; is_color (input_text[offset]); offset++);		// Ignore colours
				if (input_text[offset] == '[')
				{
					offset++;
				}
				get_name_from_text(input_text, len, 3, offset, name);		// Type 3 = ":", " " or "]"
		}
	#endif // if defined(OTHER_LIFE) && defined(OTHER_LIFE_EXTENDED_CHAT)
	if (*name && name_is_valid(name))
	{
		add_name_to_tablist(name);
	}
	else
	{
		for (offset = 0; is_color (input_text[offset]); offset++);		// Ignore colours
		get_name_from_text(input_text, len, 1, offset, name);	// Type 1 = ":", " " or is_color
	}
	if (!check_if_ignored (name))
	{
		if (channel == CHAT_PERSONAL || channel == CHAT_MODPM)
		{
			//memorise the name
			my_strcp (last_pm_from, name);
		}
		return 0;
	}
	else
	{
		return 1;
	}
}
예제 #19
0
void draw_messages (int x, int y, text_message *msgs, int msgs_size, Uint8 filter, int msg_start, int offset_start, int cursor, int width, int height, float text_zoom, select_info* select)
{
	float displayed_font_x_size = DEFAULT_FONT_X_LEN * text_zoom;
	float displayed_font_y_size = DEFAULT_FONT_Y_LEN * text_zoom;

	float selection_red = 255 / 255.0f;
	float selection_green = 162 / 255.0f;
	float selection_blue = 0;

	unsigned char cur_char;
	int i;
	int imsg, ichar;
	int cur_x, cur_y;
	int cursor_x = x-1, cursor_y = y-1;
	unsigned char ch;
	int cur_line = 0;
	int cur_col = 0;
	unsigned char last_color_char = 0;
	int in_select = 0;

	imsg = msg_start;
	ichar = offset_start;
	if (msgs[imsg].data == NULL || msgs[imsg].deleted) return;

	if (width < displayed_font_x_size || height < displayed_font_y_size)
		// no point in trying
		return;

#ifndef MAP_EDITOR2
	if (filter != FILTER_ALL)
	{
		// skip all messages of the wrong channel
		while (1)
		{
			if (skip_message(&msgs[imsg], filter))
			{
				ichar = 0;
				if (++imsg >= msgs_size) imsg = 0;
				if (msgs[imsg].data == NULL || imsg == msg_start || msgs[imsg].deleted)
					// nothing to draw
					return;
			}
			else
			{
				break;
			}
		}
		if (msgs[imsg].data == NULL || msgs[imsg].deleted) return;
	}
#endif //! MAP_EDITOR2

	ch = msgs[imsg].data[ichar];
	if (!is_color (ch))
	{
		// search backwards for the last color
		for (i = ichar-1; i >= 0; i--)
		{
			ch = msgs[imsg].data[i];
			if (is_color (ch))
			{
				find_font_char (ch);
				last_color_char = ch;
				break;
			}
		}

		if (i < 0)
		{
			// no color character found, try the message color
			if (msgs[imsg].r >= 0)
				glColor3f (msgs[imsg].r, msgs[imsg].g, msgs[imsg].b);
		}
	}

 	glEnable (GL_ALPHA_TEST);	// enable alpha filtering, so we have some alpha key
	glAlphaFunc (GL_GREATER, 0.1f);
#ifdef	NEW_TEXTURES
	bind_texture(font_text);
#else	/* NEW_TEXTURES */
	get_and_set_texture_id(font_text);
#endif	/* NEW_TEXTURES */

	i = 0;
	cur_x = x;
	cur_y = y;
	glBegin (GL_QUADS);
	while (1)
	{
		if (i == cursor)
		{
			cursor_x = cur_x;
			cursor_y = cur_y;
			if (cursor_x - x > width - displayed_font_x_size)
			{
				cursor_x = x;
				cursor_y = cur_y + displayed_font_y_size;
			}

		}

		cur_char = msgs[imsg].data[ichar];
		// watch for special characters
		if (cur_char == '\0')
		{
			// end of message
			if (++imsg >= msgs_size) {
				imsg = 0;
			}
#ifndef MAP_EDITOR2
			if (filter != FILTER_ALL)
			{
				// skip all messages of the wrong channel
				while (skip_message (&msgs[imsg], filter))
				{
					if (++imsg >= msgs_size) imsg = 0;
					if (msgs[imsg].data == NULL || imsg == msg_start) break;
				}
			}
#endif
			if (msgs[imsg].data == NULL || imsg == msg_start || msgs[imsg].deleted) break;
			rewrap_message (&msgs[imsg], text_zoom, width, NULL);
			ichar = 0;
			last_color_char = 0;
		}

		if (select != NULL && select->lines && select->lines[cur_line].msg == -1)
		{
			select->lines[cur_line].msg = imsg;
			select->lines[cur_line].chr = ichar;
		}

		if (cur_char == '\n' || cur_char == '\r' || cur_char == '\0')
		{
			// newline
			cur_y += displayed_font_y_size;
			if (cur_y - y > height - displayed_font_y_size) break;
			cur_x = x;
			if (cur_char != '\0') ichar++;
			i++;
			cur_line++;
			cur_col = 0;
			continue;
		}

		if (pos_selected(imsg, ichar, select))
		{
			if (!in_select)
			{
				glColor3f (selection_red, selection_green, selection_blue);
				in_select = 1;
			}
		}
		else
		{
			if (in_select)
			{
				if (last_color_char)
					find_font_char (last_color_char);
				else if (msgs[imsg].r < 0)
					find_font_char (to_color_char (c_grey1));
				else
					glColor3f (msgs[imsg].r, msgs[imsg].g, msgs[imsg].b);

				in_select = 0;
			}
		}

		if (is_color (cur_char))
		{
			last_color_char = cur_char;
			if (in_select)
			{
				// don't draw color characters in a selection
				i++;
				ichar++;
				continue;
			}
		}

		cur_x += draw_char_scaled (cur_char, cur_x, cur_y, displayed_font_x_size, displayed_font_y_size);
		cur_col++;

		ichar++;
		i++;
		if (cur_x - x > width - displayed_font_x_size)
		{
			// ignore rest of this line, but keep track of
			// color characters
			while (1)
			{
				ch = msgs[imsg].data[ichar];
				if (ch == '\0' || ch == '\n' || ch == '\r')
					break;
				if (is_color (ch))
					last_color_char = ch;
				ichar++;
				i++;
			}
		}
	}

	if (cursor_x >= x && cursor_y >= y && cursor_y - y <= height - displayed_font_y_size)
	{
		draw_char_scaled ('_', cursor_x, cursor_y, displayed_font_x_size, displayed_font_y_size);
	}

	glEnd();
	glDisable(GL_ALPHA_TEST);
#ifdef OPENGL_TRACE
CHECK_GL_ERRORS();
#endif //OPENGL_TRACE
}
/*There are bugs in this code that case it to not fill in an entire shape.
 * Somehow it ends at the center.
 */
int flood_fill_fast(image img, int x, int y, stack_t * borders){
	/*
	 * cur, mark, and mark2 each hold either pixel coordinates or a null value
			 NOTE: when mark is set to null, do not erase its previous coordinate value.
				   Keep those coordinates available to be recalled if necessary.
		cur-dir, mark-dir, and mark2-dir each hold a direction (left, right, up, or down)
		backtrack and findloop each hold boolean values
		count is an integer
		* 
	*/
	point_t cur, mark, mark2;
	int cur_dir, mark_dir, mark2_dir;
	bool backtrack, findloop;
	int fillcount = 0;
	bool skip_body = false;
	bool done = false;

	
	/*
	The algorithm:
	(NOTE: All directions (front, back, left, right) are relative to cur-dir)
	set cur to starting pixel
	set cur-dir to default direction
	clear mark and mark2 (set values to null)
	set backtrack and findloop to false
	*/
	cur.x = x;
	cur.y = y;
	cur_dir = UP;
	mark.x = mark.y = mark2.x = mark2.y = -1;
	backtrack = findloop = false;
	
	if(!isvalid(cur, img) || !is_color(img.data[toidx(cur, img)], CD_DETECT_COLOR)){
		return fillcount;
	}
	/*
	while front-pixel is empty
			move forward
	end while
	*/
	while(
			isvalid(move_forward(cur, cur_dir), img) &&
			is_color(img.data[toidx(move_forward(cur, cur_dir), img)], CD_DETECT_COLOR)
		){
		cur = move_forward(cur, cur_dir);
	}

	while(!done){
		int count = 0;
		int fcount = 0;
		point_t up = move_forward(cur, UP);
		point_t down = move_forward(cur, DOWN);
		point_t left = move_forward(cur, LEFT);
		point_t right = move_forward(cur, RIGHT);
		
		//count non-empty spaces
		if(!isvalid(up, img) || !is_color(img.data[toidx(up, img)], CD_DETECT_COLOR))
			count++;
		if(!isvalid(down, img) || !is_color(img.data[toidx(down, img)], CD_DETECT_COLOR))
			count++;
		if(!isvalid(left, img) || !is_color(img.data[toidx(left, img)], CD_DETECT_COLOR))
			count++;
		if(!isvalid(right, img) || !is_color(img.data[toidx(right, img)], CD_DETECT_COLOR))
			count++;
		//count filled spaces
		if(isvalid(up, img) && (is_color(img.data[toidx(up, img)], CD_FILL_COLOR)))
			fcount++;
		if(isvalid(down, img) && (is_color(img.data[toidx(down, img)], CD_FILL_COLOR)))
			fcount++;
		if(isvalid(left, img) && (is_color(img.data[toidx(left, img)], CD_FILL_COLOR)))
			fcount++;
		if(isvalid(right, img) && (is_color(img.data[toidx(right, img)], CD_FILL_COLOR)))
			fcount++;
		
		if(count - fcount > 0)
			push_stack(cur, borders);
		/*
		 * set count to number of non-diagonally adjacent pixels filled (front/back/left/right ONLY)
				if count is not 4
						do
								turn right
						while front-pixel is empty
						do
								turn left
						while front-pixel is filled
				end if
		 * 
		 */	
		if(count < 4){
			point_t front;
			do{
				cur_dir = turn_right(cur_dir);
				front = move_forward(cur, cur_dir);
			}while(isvalid(front, img) && is_color(img.data[toidx(front, img)],CD_DETECT_COLOR));
			do{
				cur_dir = turn_left(cur_dir);
				front = move_forward(cur, cur_dir);
			}while(isvalid(front, img) && !is_color(img.data[toidx(front, img)],CD_DETECT_COLOR));
			
		}	
		
		point_t back = move_forward(cur, turn_left(turn_left(cur_dir)));
		point_t front_left = move_forward(move_forward(cur, cur_dir), turn_left(cur_dir));
		point_t back_left = move_forward(move_forward(cur, turn_left(turn_left(cur_dir))), turn_left(cur_dir));
		skip_body = false;
		switch(count){
			case 4:
				/*
				  fill cur
				  done
				 */
				img.data[toidx(cur, img)] = CD_FILL_COLOR;
				fillcount++;
				
				//draw borders
				done = true;
				skip_body = true;
				//return fillcount;
				break;
			case 3:
				/*
				 clear mark
				turn left
				fill cur
				jump to PAINT
				 * 
				 */
				mark.x = mark.y = -1;
				img.data[toidx(cur, img)] = CD_FILL_COLOR;
				fillcount++;
				//jump to paint
				skip_body = true;
				break;
			case 2: 
				/*
				 if back-pixel is filled
						if front-left-pixel is not filled
								clear mark
								turn around
								fill cur
								jump to PAINT
						end if
				*/
			
				if(isvalid(back, img) && is_color(img.data[toidx(back, img)], CD_FILL_COLOR)){
					if(isvalid(front_left, img) &&!is_color(img.data[toidx(front_left, img)], CD_FILL_COLOR)){
						mark.x = mark.y = -1;
						cur_dir = turn_left(turn_left(cur_dir));
						img.data[toidx(cur, img)] = CD_FILL_COLOR;
						fillcount++;
						//jump to paint
						skip_body = true;
					}
				}
				/*
				else if mark is not set
						set mark to cur
						set mark-dir to cur-dir
						clear mark2
						set findloop and backtrack to false
				*/
				else if(mark.x == -1 && mark.y == -1){
					mark = cur;
					mark_dir = cur_dir;
					mark2.x = mark2.y = -1;
					findloop = backtrack = false;
				
				}
				else{
			/*
			 * if mark2 is not set
						if cur is at mark
								if cur-dir is the same as mark-dir
										clear mark
										turn around
										fill cur
										jump to PAINT
								else
										set backtrack to true
										set findloop to false
										set cur-dir to mark-dir
								end if
						else if findloop is true
								set mark2 to cur
								set mark2-dir to cur-dir
						end if
			 * 
			 */
			if(mark2.x == -1 && mark2.y == -1){
				if(cur.x == mark.x && cur.y == mark.y){
					if(cur_dir == mark_dir){
						mark.x = mark.y = -1;
						cur_dir = turn_left(turn_left(cur_dir));
						img.data[toidx(cur, img)] = CD_FILL_COLOR;
						fillcount++;
						//jump to paint
						skip_body = true;
					}
					else{
						backtrack = true;
						findloop = false;
						cur_dir = mark_dir;
					}
				}
				else if(findloop == true){
					mark2 = cur;
					mark2_dir = cur_dir;
				}
				
			}
			/*
			 * else
						if cur is at mark
								set cur to mark2
								set cur-dir to mark2-dir
								clear mark and mark2
								set backtrack to false
								turn around
								fill cur
								jump to PAINT
						else if cur at mark2
								set mark to cur
								set cur-dir and mark-dir to mark2-dir
								clear mark2
						end
				end if
			 * 
			 */
			 else{
				 if(cur.x == mark.x && cur.y == mark.y){
					 cur = mark2;
					 cur_dir = mark2_dir;
					 mark.x = mark.y = mark2.x = mark2.y = -1;
					 backtrack = false;
					 cur_dir = turn_left(turn_left(cur_dir));
					 img.data[toidx(cur, img)] = CD_FILL_COLOR;
					 fillcount++;
					 //jump to paint
					 skip_body = true;
					 
				 }
				 else if(cur.x == mark2.x && cur.y == mark2.y){
					 mark = cur;
					 cur_dir = mark2_dir;
					 mark_dir = mark2_dir;
					 mark2.x = mark2.y = -1;
					 
				 }
				 
			 }
			
		}
				break;
			case 1:
			case 0:
				/*
				 if backtrack is true
						set findloop to true
				else if findloop is true
						if mark is null
								restore mark
						end if
				else if front-left-pixel and back-left-pixel are both empty
						clear mark
						turn left
						fill cur
						jump to PAINT
				end if
				 *
				 */
				 if(backtrack == true){
					 findloop = true;
				 }
				 else if(findloop == true){
					 if(mark.x == -1 && mark.y == -1){
						 mark = mark2;
					 }
				 }
				 else if(isvalid(front_left, img) &&
						 isvalid(back_left, img) &&
							is_color(img.data[toidx(front_left, img)], CD_DETECT_COLOR) && 
							is_color(img.data[toidx(back_left, img)], CD_DETECT_COLOR)){
					mark.x = mark.y = -1;
					cur_dir = turn_left(cur_dir);
					img.data[toidx(cur, img)] = CD_FILL_COLOR;
					fillcount++;
					//jump to paint
					skip_body = true;
					
								
				}
				 
				break;
		}
		/*
		move forward
				if right-pixel is empty
						if backtrack is true and findloop is false and either front-pixel or left-pixel is empty
								set findloop to true
						end if
						turn right
		PAINT:
						move forward
				end if
		 * 
		 */
		if(!skip_body){
			cur = move_forward(cur, cur_dir);
			point_t right_pixel = move_forward(cur, turn_right(cur_dir));
			point_t left_pixel = move_forward(cur, turn_left(cur_dir));
			point_t front_pixel = move_forward(cur, cur_dir);
			if(isvalid(right_pixel, img) && is_color(img.data[toidx(right_pixel, img)], CD_DETECT_COLOR)){
				if(backtrack==true && findloop == false && 
					((isvalid(front_pixel, img) &&
					 is_color(img.data[toidx(front_pixel, img)], CD_DETECT_COLOR))||
					 (isvalid(left_pixel, img) &&
					 is_color(img.data[toidx(left_pixel, img)], CD_DETECT_COLOR)))
				 )
				 {
					findloop = true; 
				 }
				 cur_dir = turn_right(cur_dir);
				 cur = move_forward(cur, cur_dir);
			}
			
			
		}
		else
			cur = move_forward(cur, cur_dir);
			
	
    }
    #ifdef DEBUG
		int i,n = stack_size(borders);
		for(i=0; i < n ; i++){
			point_t p = borders->s[i];
			if(isvalid(p, img)){
				img.data[toidx(p, img)] = CD_BORDER_COLOR;
			}
		}
	#endif
	return fillcount;
    
   
}