[C++] 327 BBS閲覧アプリの製作 その13 右寄せ用Fl_Input継承クラス

[M1 Mac, MacOS Ventura 13.3.1, clang 14.0.3]

スレッド番号とレス数をFl_Inputで左寄せ表示していたのですが、継承クラスで右寄せ用にしました。

narkiveという掲示板で17年前(2006年)にコードがアップされていました。クラスファイル化して使わせていただきます。ありがたいことです。

Fl_InputではGUI上のデータを編集できてしまうので、本当はFl_Boxで表示させたいのですが上手くできません。

あとレス表示欄も改行を入れるなどして見やすくしました。

次に手掛けるとしたら、スレッド一覧やスレッドのリロード、未読レスのカウントあたりでしょうか。

今のところ画像表示はできませんが、AIを使って内容の安全性を確認できたら面白いかもしれません。

それにしてもFLTKに関してはChatGPTは役に立たないどころか、あることないことでっち上げてマイナス面が大きいです。ネット情報、ユーザーの少なさの証左でもあり寂しくなります。

#include "InputRt.h"

InputRt::InputRt(int x, int y, int w, int h, const char *title = 0) : Fl_Input(x, y, w, h, title){};

InputRt::~InputRt(){}

void InputRt::draw(void){
	if (input_type() == FL_HIDDEN_INPUT) return;

	// Simplest to just redraw the whole box every time...
	Fl_Boxtype b = box();
	damage(FL_DAMAGE_ALL);
	draw_box(b, color());

	int xo = x()+Fl::box_dx(b);
	int yo = y()+Fl::box_dy(b);
	int wo = w()-Fl::box_dw(b);
	int ho = h()-Fl::box_dh(b);
	int wt, ht;
	char buf[128];

	// How long is the string to display?
	strncpy(buf, value(), 128);
	wt = 0; ht = 0;
	fl_measure(buf, wt, ht);

	// Make the text window be at the right hand end
	wt = wt + 5;
	xo = xo + wo - wt;
	wo = wt;

	// Update the text window
	Fl_Input_::drawtext(xo, yo, wo, ho);
}
#include <string.h>
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>

class InputRt : public Fl_Input{
	public:
		InputRt(int x, int y, int w, int h, const char *title);
		~InputRt();
		
	protected:
		void draw(void);

	private:
};

参考サイト

[C++] 326 BBS閲覧アプリの製作 その12 レスのGUI表示 Fl_Text_Display

[M1 Mac, MacOS Ventura 13.3.1, clang 14.0.3]

レスを右下に表示できるようになりました。

シフトJISのdatファイルとして一旦保存してしまうと、UTF-8への変換が自分のスキルではかなり難しいので、文字列の状態で変換してからファイルにしました。macOSは日本語を扱う上で不利になることが多いです。

これで基本機能の実装は完了です。だらだら作って4日半でした。GUIは丸一日掛かりました。

レス表示欄は生データそのままなのでかなり見づらいです。テキスト整形は今後の課題とします。

extern vector<tuple<string, string, string, string>> numTitlePostnumID;
extern string id, num, title, postnum, boardURL;
extern vector<tuple<string, string, string>> urlNameCat;
extern Fl_Text_Display* contentDisplay;

void button_cb(Fl_Widget *w, void*) {
    string selectID;
    const char* label = w->label();

    cout << "label: " << label << endl;

    for (const auto& tuple : numTitlePostnumID) {
        if (std::get<1>(tuple) == label) {
            selectID = std::get<3>(tuple);
        }
    }

    string url = boardURL + "dat/" + selectID + ".dat";
    std::string datBuffer;

    string filename = "/Users/[ユーザ名]/BBS_Browser/" + selectID + ".dat";

    cout << "url: " << url << endl;
    cout << "filename: " << filename << endl;

    CURL* curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &datBuffer);
        CURLcode res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            std::cerr << "Error: " << curl_easy_strerror(res) << std::endl;
            return;
        }

        curl_easy_cleanup(curl);

    } else {
        std::cerr << "Failed to initialize curl" << std::endl;

        return;
    }

    // 文字コードをCP932からUTF-8へ変換
    datBuffer = ConvertShiftJISToUTF8(datBuffer);

    std::ofstream file(filename, std::ios::binary);
    file << datBuffer;
    file.close();

    // ファイル内容表示
    std::ifstream ifile(filename);
    if (!ifile.is_open()) {
        cout << "ファイルopen失敗" << endl;

        return;
    }

    Fl_Text_Buffer* buffer = new Fl_Text_Buffer();
    contentDisplay->buffer(buffer);

    string line;
    while (std::getline(ifile, line)) {
        buffer->append(line.c_str());
        buffer->append("\n");
    }

    // 現在の行数を取得
    int lineCount = contentDisplay -> buffer() -> count_lines(0, contentDisplay -> buffer() -> length());
    // 最終行が見えるようにスクロールを設定
    contentDisplay -> scroll(lineCount, 0);

    ifile.close();

    return;
}