2

I am using FLTK 1.3.5 and I would like to use the Multiline_Input object. I wonder if there is a way to automatically put a newline when the inserted text reaches the end of the input field, instead of doing it manually (check the uploaded images for an example). Moreover, the newline should be put at the end of a word. I searched here on SO and on the web, but I was not able to find anything useful.

Input text on one line Input text on multiple lines

Here it is the code used to generate the images above.

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Multiline_Input.H>


int main(int argc, char **argv) {

    Fl_Window *G_win = 0;
    G_win = new Fl_Window(200,200,"Test multi input");

    Fl_Multiline_Input* in;
    in = new Fl_Multiline_Input(50,50,120,100," Test:");

    G_win->end();
    G_win->show(argc, argv);
    
    return Fl::run();
}
Eddymage
  • 1,008
  • 1
  • 7
  • 22

2 Answers2

1

With FLTK, you can always catch keyboard events, e.g. using (or redefining) keyboard events

A human being don't type very fast, and computers are fast. Your keyboard event handler could change the multiline content at every keystroke

We plan to do so (in summer 2020) in the RefPerSys project.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • I thought indeed about checking the length of the string at each keyboard input, something like `length(string)>input_filed? string+=\n: ; `, but I was wondering if there is something already coded in FLTK. I will try the approach you suggest. – Eddymage Jul 13 '20 at 07:09
1

Following Basile's suggestion, I investigated more on handling events and then I came up with a solution.

I derivated a class from the original Fl_Multiline_Input which basically controls that the char[] in Fl_Multiline_input->value() does not overcome the maximum width given by the geometry (considering the current Fl_font). Maybe it is not the best solution but, hey, it works! Of course, more performant/elegant strategies are more than welcome.

The code is down below.

#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);   
        }
}
Eddymage
  • 1,008
  • 1
  • 7
  • 22