Следуя предложению Базиля, я больше исследовал обработку событий, а затем пришел к решению.
Я создал класс из исходного Fl_Multiline_Input
, который в основном контролирует, что char[]
в Fl_Multiline_input->value()
не превышает максимальную ширину, заданную геометрией (учитывая текущую Fl_font
). Может быть, это не лучшее решение, но, эй, работает! Конечно, более производительные / элегантные стратегии более чем приветствуются.
Код ниже.
#include "mymulti.hpp"
/*
This is needed for converting a std::string
to a char[] (required by Fl_Input). Again,
maybe more performant alternative are out there...
*/
char* str2char(std::string S){
char *out;
out = (char*) malloc ((S.size()+1)*sizeof(char));
strcpy(out,&S[0]);
out[S.size()] = '\0';
return out;
}
mymulti::mymulti(int x, int y, int h, int l):Fl_Multiline_Input(x, y, h,l)
{}
int mymulti::handle(int event)
{
switch (event) {
// When a key is pressed and the widget is waiting for input
case FL_KEYBOARD:
return handle_key(event, Fl::event_key());
default:
return Fl_Multiline_Input::handle(event);
};
}
int mymulti::handle_key(int event, int key) {
if (key==FL_BackSpace)
// Allowing Fl_Multiline_Input to handle the delection of characters
return Fl_Multiline_Input::handle(event);
else{
// Converting to std::string just because manipulation is easer
std::string s(this->value());
std::string s2;
/*
Search for the last newline char:
the subsequent substring must be shorter
than the width of the input field
*/
std::size_t found = s.find_last_of("\n");
if (found<std::string::npos)
s2= s.substr (found);
else
s2 = s;
/*
Mean length of a char (lower case)
under the current fl_font. One can add
uppercase letters and/or numbers and/or
other symbols.
*/
double lc = fl_width("abcdefghijklmnopqrstuvwxyz")/26;
// Maximum length for the substring
int string_length = this->w()/lc -1;
// if the substring is longer than the max allowed length, then add a newline
if (s2.length()>string_length)
s+="\n";
// Update the input field
this->value(str2char(s));
return Fl_Multiline_Input::handle(event);
}
}