Merge branch 'master' into jgrpp
# Conflicts: # .github/workflows/ci-build.yml # .github/workflows/release-linux.yml # .github/workflows/release-macos.yml # .github/workflows/release-source.yml # .github/workflows/release.yml # CMakeLists.txt # COMPILING.md # src/ai/ai_core.cpp # src/ai/ai_gui.cpp # src/bridge_gui.cpp # src/company_gui.cpp # src/console_cmds.cpp # src/core/CMakeLists.txt # src/core/smallmap_type.hpp # src/disaster_vehicle.h # src/effectvehicle_base.h # src/fontcache.cpp # src/game/game_core.cpp # src/game/game_gui.cpp # src/gamelog.cpp # src/gamelog_internal.h # src/group_gui.cpp # src/linkgraph/linkgraph.h # src/misc.cpp # src/network/core/config.h # src/network/core/udp.cpp # src/network/network_chat_gui.cpp # src/network/network_content_gui.cpp # src/network/network_gui.cpp # src/newgrf.cpp # src/newgrf_gui.cpp # src/newgrf_profiling.cpp # src/newgrf_profiling.h # src/object_gui.cpp # src/openttd.cpp # src/openttd.h # src/order_gui.cpp # src/os/windows/font_win32.cpp # src/rail_gui.cpp # src/road.cpp # src/road_gui.cpp # src/saveload/afterload.cpp # src/saveload/saveload.h # src/script/api/script_controller.cpp # src/script/api/script_roadtypelist.cpp # src/script/script_config.cpp # src/script/script_config.hpp # src/script/script_instance.cpp # src/script/script_scanner.cpp # src/script/squirrel.cpp # src/script/squirrel_helper.hpp # src/settings_gui.cpp # src/settings_internal.h # src/settings_type.h # src/table/settings/network_private_settings.ini # src/timetable_gui.cpp # src/vehicle.cpp # src/vehicle_base.h # src/window_gui.h
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "network.h"
|
||||
#include "network_client.h"
|
||||
#include "network_base.h"
|
||||
#include "../3rdparty/fmt/format.h"
|
||||
|
||||
#include "../widgets/network_chat_widget.h"
|
||||
|
||||
@@ -28,6 +29,7 @@
|
||||
|
||||
#include <stdarg.h> /* va_list */
|
||||
#include <deque>
|
||||
#include <optional>
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
@@ -326,18 +328,16 @@ struct NetworkChatWindow : public Window {
|
||||
* Find the next item of the list of things that can be auto-completed.
|
||||
* @param item The current indexed item to return. This function can, and most
|
||||
* likely will, alter item, to skip empty items in the arrays.
|
||||
* @return Returns the char that matched to the index.
|
||||
* @return Returns the view that matched to the index.
|
||||
*/
|
||||
const char *ChatTabCompletionNextItem(uint *item)
|
||||
std::optional<std::string> ChatTabCompletionNextItem(uint *item)
|
||||
{
|
||||
static char chat_tab_temp_buffer[64];
|
||||
|
||||
/* First, try clients */
|
||||
if (*item < MAX_CLIENT_SLOTS) {
|
||||
/* Skip inactive clients */
|
||||
for (NetworkClientInfo *ci : NetworkClientInfo::Iterate(*item)) {
|
||||
*item = ci->index;
|
||||
return ci->client_name.c_str();
|
||||
return ci->client_name;
|
||||
}
|
||||
*item = MAX_CLIENT_SLOTS;
|
||||
}
|
||||
@@ -349,12 +349,11 @@ struct NetworkChatWindow : public Window {
|
||||
for (const Town *t : Town::Iterate(*item - MAX_CLIENT_SLOTS)) {
|
||||
/* Get the town-name via the string-system */
|
||||
SetDParam(0, t->index);
|
||||
GetString(chat_tab_temp_buffer, STR_TOWN_NAME, lastof(chat_tab_temp_buffer));
|
||||
return &chat_tab_temp_buffer[0];
|
||||
return GetString(STR_TOWN_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -362,13 +361,14 @@ struct NetworkChatWindow : public Window {
|
||||
* the word right from that as to complete. It also writes a \0 at the
|
||||
* position of the space (if any). If nothing found, buf is returned.
|
||||
*/
|
||||
static char *ChatTabCompletionFindText(char *buf)
|
||||
static std::string_view ChatTabCompletionFindText(std::string_view &buf)
|
||||
{
|
||||
char *p = strrchr(buf, ' ');
|
||||
if (p == nullptr) return buf;
|
||||
auto it = buf.find_last_of(' ');
|
||||
if (it == std::string_view::npos) return buf;
|
||||
|
||||
*p = '\0';
|
||||
return p + 1;
|
||||
std::string_view res = buf.substr(it + 1);
|
||||
buf.remove_suffix(res.size() + 1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -376,46 +376,44 @@ struct NetworkChatWindow : public Window {
|
||||
*/
|
||||
void ChatTabCompletion()
|
||||
{
|
||||
static char _chat_tab_completion_buf[NETWORK_CHAT_LENGTH];
|
||||
assert(this->message_editbox.text.max_bytes == lengthof(_chat_tab_completion_buf));
|
||||
static std::string _chat_tab_completion_buf;
|
||||
|
||||
Textbuf *tb = &this->message_editbox.text;
|
||||
size_t len, tb_len;
|
||||
uint item;
|
||||
char *tb_buf, *pre_buf;
|
||||
const char *cur_name;
|
||||
uint item = 0;
|
||||
bool second_scan = false;
|
||||
|
||||
item = 0;
|
||||
/* Create views, so we do not need to copy the data for now. */
|
||||
std::string_view pre_buf = _chat_tab_completion_active ? std::string_view(_chat_tab_completion_buf) : std::string_view(tb->buf);
|
||||
std::string_view tb_buf = ChatTabCompletionFindText(pre_buf);
|
||||
|
||||
/* Copy the buffer so we can modify it without damaging the real data */
|
||||
pre_buf = (_chat_tab_completion_active) ? stredup(_chat_tab_completion_buf) : stredup(tb->buf);
|
||||
/*
|
||||
* Comparing pointers of the data, as both "Hi:<tab>" and "Hi: Hi:<tab>" will result in
|
||||
* tb_buf and pre_buf being "Hi:", which would be equal in content but not in context.
|
||||
*/
|
||||
bool begin_of_line = tb_buf.data() == pre_buf.data();
|
||||
|
||||
tb_buf = ChatTabCompletionFindText(pre_buf);
|
||||
tb_len = strlen(tb_buf);
|
||||
|
||||
while ((cur_name = ChatTabCompletionNextItem(&item)) != nullptr) {
|
||||
std::optional<std::string> cur_item;
|
||||
while ((cur_item = ChatTabCompletionNextItem(&item)).has_value()) {
|
||||
std::string_view cur_name = cur_item.value();
|
||||
item++;
|
||||
|
||||
if (_chat_tab_completion_active) {
|
||||
/* We are pressing TAB again on the same name, is there another name
|
||||
* that starts with this? */
|
||||
if (!second_scan) {
|
||||
size_t offset;
|
||||
size_t length;
|
||||
std::string_view view;
|
||||
|
||||
/* If we are completing at the begin of the line, skip the ': ' we added */
|
||||
if (tb_buf == pre_buf) {
|
||||
offset = 0;
|
||||
length = (tb->bytes - 1) - 2;
|
||||
if (begin_of_line) {
|
||||
view = std::string_view(tb->buf, (tb->bytes - 1) - 2);
|
||||
} else {
|
||||
/* Else, find the place we are completing at */
|
||||
offset = strlen(pre_buf) + 1;
|
||||
length = (tb->bytes - 1) - offset;
|
||||
size_t offset = pre_buf.size() + 1;
|
||||
view = std::string_view(tb->buf + offset, (tb->bytes - 1) - offset);
|
||||
}
|
||||
|
||||
/* Compare if we have a match */
|
||||
if (strlen(cur_name) == length && strncmp(cur_name, tb->buf + offset, length) == 0) second_scan = true;
|
||||
if (cur_name == view) second_scan = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -423,21 +421,19 @@ struct NetworkChatWindow : public Window {
|
||||
/* Now any match we make on _chat_tab_completion_buf after this, is perfect */
|
||||
}
|
||||
|
||||
len = strlen(cur_name);
|
||||
if (tb_len < len && StrStartsWith(cur_name, tb_buf)) {
|
||||
if (tb_buf.size() < cur_name.size() && StrStartsWith(cur_name, tb_buf)) {
|
||||
/* Save the data it was before completion */
|
||||
if (!second_scan) seprintf(_chat_tab_completion_buf, lastof(_chat_tab_completion_buf), "%s", tb->buf);
|
||||
if (!second_scan) _chat_tab_completion_buf = tb->buf;
|
||||
_chat_tab_completion_active = true;
|
||||
|
||||
/* Change to the found name. Add ': ' if we are at the start of the line (pretty) */
|
||||
if (pre_buf == tb_buf) {
|
||||
this->message_editbox.text.Print("%s: ", cur_name);
|
||||
if (begin_of_line) {
|
||||
this->message_editbox.text.Assign(fmt::format("{}: ", cur_name));
|
||||
} else {
|
||||
this->message_editbox.text.Print("%s %s", pre_buf, cur_name);
|
||||
this->message_editbox.text.Assign(fmt::format("{} {}", pre_buf, cur_name));
|
||||
}
|
||||
|
||||
this->SetDirty();
|
||||
free(pre_buf);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -449,7 +445,6 @@ struct NetworkChatWindow : public Window {
|
||||
|
||||
this->SetDirty();
|
||||
}
|
||||
free(pre_buf);
|
||||
}
|
||||
|
||||
Point OnInitialPosition(int16 sm_width, int16 sm_height, int window_number) override
|
||||
|
Reference in New Issue
Block a user