Пример #1
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
}
Пример #2
0
message::cli_res message::extract_opts(std::vector<cli_arg> xs,
                                       help_factory f, bool no_help) const {
  std::string helpstr;
  auto make_error = [&](std::string err) -> cli_res {
    return {*this, std::set<std::string>{}, std::move(helpstr), std::move(err)};
  };
  // add default help item if user did not specify any help option
  auto pred = [](const cli_arg& arg) -> bool {
    std::vector<std::string> s;
    split(s, arg.name, is_any_of(","), token_compress_on);
    if (s.empty())
      return false;
    auto has_short_help = [](const std::string& opt) {
      return opt.find_first_of("h?") != std::string::npos;
    };
    return s[0] == "help"
           || std::find_if(s.begin() + 1, s.end(), has_short_help) != s.end();
  };
  if (! no_help && std::none_of(xs.begin(), xs.end(), pred)) {
    xs.push_back(cli_arg{"help,h,?", "print this text"});
  }
  std::map<std::string, cli_arg*> shorts;
  std::map<std::string, cli_arg*> longs;
  for (auto& cliarg : xs) {
    std::vector<std::string> s;
    split(s, cliarg.name, is_any_of(","), token_compress_on);
    if (s.empty()) {
      return make_error("invalid option name: " + cliarg.name);
    }
    longs["--" + s.front()] = &cliarg;
    for (size_t i = 1; i < s.size(); ++i) {
      if (s[i].size() != 1) {
        return make_error("invalid short option name: " + s[i]);
      }
      shorts["-" + s[i]] = &cliarg;
    }
    // generate helptext for this item
    auto& ht = cliarg.helptext;
    if (s.size() == 1) {
      ht += "--";
      ht += s.front();
    } else {
      ht += "-";
      ht += s[1];
      ht += " [";
      for (size_t i = 2; i < s.size(); ++i) {
        ht += "-";
        ht += s[i];
        ht += ",";
      }
      ht += "--";
      ht += s.front();
      ht += "]";
    }
    if (cliarg.fun) {
      ht += " arg";
    }
  }
  if (f) {
    helpstr = f(xs);
  } else {
    auto op = [](size_t tmp, const cli_arg& arg) {
      return std::max(tmp, arg.helptext.size());
    };
    auto name_width = std::accumulate(xs.begin(), xs.end(), size_t{0}, op);
    std::ostringstream oss;
    oss << std::left;
    oss << "Allowed options:" << std::endl;
    for (auto& ca : xs) {
      oss << "  ";
      oss.width(static_cast<std::streamsize>(name_width));
      oss << ca.helptext << "  : " << ca.text << std::endl;
    }
    helpstr = oss.str();
  }
  std::set<std::string> opts;
  auto insert_opt_name = [&](const cli_arg* ptr) {
    auto separator = ptr->name.find(',');
    if (separator == std::string::npos) {
      opts.insert(ptr->name);
    } else {
      opts.insert(ptr->name.substr(0, separator));
    }
  };
  // we can't `return make_error(...)` from inside `extract`, hence we
  // store any occurred error in a temporary variable returned at the end
  std::string error;
  auto res = extract({
    [&](const std::string& arg) -> optional<skip_message_t> {
      if (arg.empty() || arg.front() != '-') {
        return skip_message();
      }
      auto i = shorts.find(arg.substr(0, 2));
      if (i != shorts.end()) {
        if (i->second->fun) {
          // this short opt expects two arguments
          if (arg.size() > 2) {
             // this short opt comes with a value (no space), e.g., -x2
            if (! i->second->fun(arg.substr(2))) {
              error = "invalid value for " + i->second->name + ": " + arg;
              return skip_message();
            }
            insert_opt_name(i->second);
            return none;
          }
          // no value given, try two-argument form below
          return skip_message();
        }
        insert_opt_name(i->second);
        return none;
      }
      auto eq_pos = arg.find('=');
      auto j = longs.find(arg.substr(0, eq_pos));
      if (j != longs.end()) {
        if (j->second->fun) {
          if (eq_pos == std::string::npos) {
            error =  "missing argument to " + arg;
            return skip_message();
          }
          if (! j->second->fun(arg.substr(eq_pos + 1))) {
            error = "invalid value for " + j->second->name + ": " + arg;
            return skip_message();
          }
          insert_opt_name(j->second);
          return none;
        }
        insert_opt_name(j->second);
        return none;
      }
      error = "unknown command line option: " + arg;
      return skip_message();
    },
    [&](const std::string& arg1,
        const std::string& arg2) -> optional<skip_message_t> {
      if (arg1.size() < 2 || arg1[0] != '-' || arg1[1] == '-') {
        return skip_message();
      }
      auto i = shorts.find(arg1.substr(0, 2));
      if (i != shorts.end()) {
        if (! i->second->fun || arg1.size() > 2) {
          // this short opt either expects no argument or comes with a value
          // (no  space), e.g., -x2, so we have to parse it with the
          // one-argument form above
          return skip_message();
        }
        CAF_ASSERT(arg1.size() == 2);
        if (! i->second->fun(arg2)) {
          error = "invalid value for option " + i->second->name + ": " + arg2;
          return skip_message();
        }
        insert_opt_name(i->second);
        return none;
      }
      error = "unknown command line option: " + arg1;
      return skip_message();
    }
  });
  return {res, std::move(opts), std::move(helpstr), std::move(error)};
}