Big changes.

Wrote a class for using curl without c style memory management. Started
parsing percentages as well. Worked on the GUI a bit and have it ready
for a split pane view.
This commit is contained in:
Inventor Xtreme 2026-03-25 22:53:52 -04:00
parent 8f975735b2
commit 1a89c97a5c
8 changed files with 247 additions and 10 deletions

View file

@ -4,7 +4,7 @@ CXX = g++
CPPFLAGS = -g CPPFLAGS = -g
CFLAGS = -g CFLAGS = -g
LDFLAGS = -g LDFLAGS = -g
LDLIBS = -lfltk LDLIBS = -lfltk -lcurl -lfltk_images
SRC_DIR = src SRC_DIR = src

9
README.md Normal file
View file

@ -0,0 +1,9 @@
# MossMan
MossMan is a tool designed to ease the filtering, viewing, and compilation of [Stanford MOSS](https://theory.stanford.edu/~aiken/moss/). It is specialized for CMU's 15-122 programing course, generating the outline of a file that is read by another script. It could be used for other courses however.
## Adding images
Because distributed an application (normally) would require the inclusion of multiple files that then must be grouped and installed (especially on Windows), we (read: I) chose to embed files into the executable itself for things like icons. Using xxd -i is recommended to generate the code needed. Note that modifications will need to be made to fit naming conventions and keeping the actual data out of the header to ease compilation times.

BIN
search_file_2-4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 B

44
src/curlwrap.cpp Normal file
View file

@ -0,0 +1,44 @@
#include <iostream>
#include "curlwrap.hpp"
#include <curl/curl.h>
#include <curl/easy.h>
#include <string>
size_t writeback(char * ptr, size_t size, size_t nmemb, void * data) {
std::string* us = (std::string*) data;
us->append(ptr, nmemb);
return nmemb;
}
Curl::Curl() {
handle = curl_easy_init();
}
Curl::~Curl() {
if (handle) {
curl_easy_cleanup(handle);
}
}
void Curl::seturl(std::string url) {
data = "";
curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, writeback);
curl_easy_setopt(handle, CURLOPT_WRITEDATA, &data);
}
std::string Curl::get() {
curl_easy_perform(handle);
return data;
}

21
src/curlwrap.hpp Normal file
View file

@ -0,0 +1,21 @@
#ifndef CURLWRAP_HEADER
#define CURLWRAP_HEADER
#include <curl/curl.h>
#include <string>
struct Curl {
CURL * handle;
std::string data;
Curl();
~Curl();
void seturl(std::string url);
std::string get();
};
#endif

67
src/images.cpp Normal file
View file

@ -0,0 +1,67 @@
unsigned char icon_inspect_file_png[] = {
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30,
0x08, 0x03, 0x00, 0x00, 0x00, 0x60, 0xdc, 0x09, 0xb5, 0x00, 0x00, 0x00,
0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, 0xb1, 0x8f, 0x0b, 0xfc, 0x61,
0x05, 0x00, 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a,
0x26, 0x00, 0x00, 0x80, 0x84, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0x80,
0xe8, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, 0x3a,
0x98, 0x00, 0x00, 0x17, 0x70, 0x9c, 0xba, 0x51, 0x3c, 0x00, 0x00, 0x00,
0x75, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x00, 0x00, 0x77, 0x77, 0x77, 0x86,
0x86, 0x86, 0xff, 0xfb, 0xf0, 0x99, 0x99, 0x99, 0x55, 0x55, 0x55, 0xea,
0xea, 0xea, 0xcc, 0xcc, 0xcc, 0xd7, 0xd7, 0xd7, 0xe7, 0xe7, 0xd6, 0x99,
0xcc, 0xff, 0x99, 0x99, 0xcc, 0x5f, 0x5f, 0x5f, 0x99, 0xff, 0xff, 0xc0,
0xc0, 0xc0, 0xcc, 0xff, 0xff, 0xcc, 0xff, 0xcc, 0x66, 0xff, 0xff, 0x33,
0xff, 0xff, 0x4d, 0x4d, 0x4d, 0x33, 0x33, 0x33, 0xcc, 0xec, 0xff, 0x00,
0xff, 0xff, 0x11, 0x11, 0x11, 0x66, 0x66, 0x66, 0x1c, 0x1c, 0x1c, 0x22,
0x22, 0x22, 0xb2, 0xb2, 0xb2, 0x00, 0x66, 0xff, 0x00, 0x33, 0x99, 0x00,
0xcc, 0xff, 0x00, 0x99, 0xff, 0x00, 0x66, 0x99, 0x00, 0x33, 0xcc, 0x00,
0x00, 0x80, 0x00, 0x00, 0x66, 0x00, 0x00, 0xff, 0x00, 0x33, 0x66, 0xff,
0xff, 0xff, 0x1d, 0x20, 0xae, 0x06, 0x00, 0x00, 0x00, 0x01, 0x74, 0x52,
0x4e, 0x53, 0x00, 0x40, 0xe6, 0xd8, 0x66, 0x00, 0x00, 0x00, 0x01, 0x62,
0x4b, 0x47, 0x44, 0x26, 0x5a, 0x08, 0x98, 0xb5, 0x00, 0x00, 0x00, 0x07,
0x74, 0x49, 0x4d, 0x45, 0x07, 0xe2, 0x06, 0x1a, 0x00, 0x32, 0x12, 0x39,
0x75, 0x77, 0x4b, 0x00, 0x00, 0x01, 0x74, 0x49, 0x44, 0x41, 0x54, 0x48,
0xc7, 0xed, 0xd4, 0xcb, 0x56, 0x83, 0x30, 0x14, 0x05, 0xd0, 0x86, 0xbc,
0x9a, 0x94, 0x90, 0x04, 0x0a, 0x56, 0x05, 0x5b, 0xad, 0xfe, 0xff, 0x2f,
0x7a, 0x6f, 0x12, 0xa4, 0xba, 0xc2, 0xa3, 0x13, 0x97, 0x03, 0xcf, 0xa4,
0x0c, 0xd8, 0xdc, 0x93, 0x90, 0xb2, 0xdb, 0xfd, 0xe7, 0x4f, 0x86, 0x14,
0x3f, 0xb2, 0x0a, 0xe8, 0xf7, 0x30, 0x7e, 0x2f, 0x58, 0x13, 0x44, 0x40,
0x6e, 0x81, 0x5c, 0x12, 0x24, 0x66, 0x2f, 0xd4, 0x04, 0xd4, 0xbc, 0x20,
0x44, 0x63, 0x0e, 0x84, 0x97, 0xfb, 0xaf, 0x29, 0x8c, 0xce, 0x0a, 0xa2,
0x4d, 0xa5, 0xac, 0x71, 0xd6, 0xeb, 0xb2, 0x94, 0xe3, 0x10, 0x46, 0xe7,
0x04, 0xd1, 0xd6, 0x02, 0xb0, 0x35, 0x44, 0x97, 0x5c, 0x4a, 0xa5, 0xd0,
0xf0, 0xe6, 0x88, 0xc9, 0x01, 0xab, 0x00, 0x38, 0xcb, 0x30, 0x30, 0x83,
0xc3, 0x0f, 0x00, 0x21, 0x2b, 0xc6, 0x08, 0xcf, 0x0f, 0xa0, 0x38, 0xc1,
0x8a, 0xd6, 0xfb, 0x4e, 0x97, 0x4c, 0xc6, 0x75, 0x04, 0x91, 0x03, 0x86,
0x0a, 0x04, 0xae, 0x0e, 0xd1, 0x1c, 0x40, 0x5c, 0x05, 0x8a, 0x3c, 0xa0,
0x61, 0x42, 0xa8, 0xc4, 0x24, 0x4c, 0x50, 0x31, 0x28, 0xf2, 0x00, 0x2b,
0x39, 0x6b, 0x5b, 0x67, 0x3c, 0x6c, 0x14, 0x67, 0x29, 0x38, 0x23, 0x0b,
0x84, 0x15, 0xe3, 0x2e, 0xe1, 0x3e, 0xe1, 0x1a, 0x44, 0x7a, 0xed, 0x59,
0xe0, 0x8d, 0x68, 0x71, 0x0d, 0xa9, 0x52, 0x33, 0x55, 0x9a, 0x01, 0xda,
0xb7, 0x0e, 0x27, 0x38, 0x67, 0x3a, 0xd8, 0xa5, 0xa6, 0x99, 0x2a, 0x65,
0x01, 0x8c, 0xf0, 0xf8, 0x1e, 0x4c, 0x68, 0xd4, 0x15, 0x4d, 0xb5, 0x52,
0x09, 0x46, 0xd4, 0xbe, 0x52, 0xc6, 0x87, 0xa7, 0x16, 0x0f, 0xc5, 0xd8,
0x68, 0xae, 0x12, 0x0a, 0x5d, 0xa9, 0xda, 0x77, 0x90, 0x02, 0x0e, 0x43,
0x33, 0xfe, 0xf7, 0x66, 0x01, 0x9c, 0xd6, 0x43, 0x38, 0xae, 0x92, 0x1c,
0x19, 0x3b, 0x1d, 0x61, 0xc6, 0x62, 0xa5, 0x48, 0xc8, 0x23, 0xe4, 0x89,
0xd1, 0xe7, 0x53, 0x3f, 0xa4, 0x56, 0x4b, 0x00, 0x8d, 0x84, 0x10, 0x75,
0x7a, 0x39, 0xf7, 0x43, 0xb3, 0x52, 0x29, 0x82, 0xf0, 0xd4, 0x4b, 0xdf,
0xa1, 0x08, 0xad, 0xd6, 0x00, 0x0d, 0xc5, 0x2f, 0x67, 0x14, 0xaf, 0x20,
0xe8, 0x2a, 0x88, 0x89, 0x62, 0x88, 0x62, 0x0b, 0x48, 0xe2, 0x2d, 0x88,
0x4d, 0x20, 0x89, 0x2b, 0x8a, 0x6d, 0x60, 0x12, 0xeb, 0xdb, 0x9a, 0x32,
0x44, 0xc1, 0x16, 0xbf, 0x7e, 0x84, 0xdf, 0x04, 0x45, 0x7f, 0xc5, 0xab,
0xdd, 0xc6, 0x0c, 0xe7, 0xfe, 0xfd, 0x63, 0xeb, 0xcd, 0x51, 0x0c, 0xc3,
0x5d, 0xf7, 0xff, 0xe7, 0x97, 0xf2, 0x09, 0x81, 0xc5, 0x1c, 0x78, 0xc0,
0x82, 0x16, 0xc0, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74, 0x64,
0x61, 0x74, 0x65, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x00, 0x32,
0x30, 0x31, 0x38, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x36, 0x54, 0x30, 0x30,
0x3a, 0x35, 0x30, 0x3a, 0x31, 0x38, 0x2d, 0x30, 0x34, 0x3a, 0x30, 0x30,
0x0e, 0x62, 0x1d, 0x0e, 0x00, 0x00, 0x00, 0x25, 0x74, 0x45, 0x58, 0x74,
0x64, 0x61, 0x74, 0x65, 0x3a, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x00,
0x32, 0x30, 0x31, 0x38, 0x2d, 0x30, 0x36, 0x2d, 0x32, 0x36, 0x54, 0x30,
0x30, 0x3a, 0x35, 0x30, 0x3a, 0x31, 0x38, 0x2d, 0x30, 0x34, 0x3a, 0x30,
0x30, 0x7f, 0x3f, 0xa5, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e,
0x44, 0xae, 0x42, 0x60, 0x82
};
unsigned int icon_inspect_file_png_len = 761;

11
src/images.h Normal file
View file

@ -0,0 +1,11 @@
#ifndef IMAGES_H
#define IMAGES_H
#include <cstddef>
extern unsigned char icon_inspect_file_png[];
extern size_t icon_inspect_file_png_len;
#endif

View file

@ -1,16 +1,23 @@
#include <FL/Enumerations.H> #include <FL/Enumerations.H>
#include <FL/Fl_Widget.H>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include "testcpp.hpp" #include "testcpp.hpp"
#include "curlwrap.hpp"
#include "images.h"
#include <FL/Fl_Window.H> #include <FL/Fl_Window.H>
#include <FL/Fl_Box.H> #include <FL/Fl_Box.H>
#include <FL/Fl_Multi_Browser.H> #include <FL/Fl_Multi_Browser.H>
#include <FL/Fl.H> #include <FL/Fl.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_PNG_Image.H>
#include <FL/fl_ask.H>
#include <FL/Fl_Flex.H>
#include <memory> #include <memory>
#include <string>
#include <vector> #include <vector>
using namespace std; using namespace std;
@ -39,8 +46,11 @@ struct BasicEntry {
std::string matchlink; std::string matchlink;
int Apercent;
int Bpercent;
std::string toString() const { std::string toString() const {
return "{(BasicEntry): " + A.toString() + ", " + B.toString() + ", " + matchlink + "}"; return "{(BasicEntry): " + A.toString() + ", " + B.toString() + ", " + matchlink + + ", " + std::to_string(Apercent) + "%, " + std::to_string(Bpercent) + "%}";
} }
}; };
@ -51,6 +61,26 @@ std::ostream& operator<<(std::ostream& os, const BasicEntry& e) {
} }
struct Selected {
Fl_Multi_Browser& browser;
Selected(Fl_Multi_Browser& browser_in) : browser(browser_in) {}
};
void show_callback(Fl_Widget *w, void * data) {
Selected * rdata = (Selected *) data;
auto s = rdata->browser.size() + 1;
for (size_t i = 0; i < s; i++) {
if (rdata->browser.selected(i)) {
fl_alert("%s", rdata->browser.text(i));
}
}
}
std::vector<BasicEntry> MakeEntires(std::string filename) { std::vector<BasicEntry> MakeEntires(std::string filename) {
std::vector<BasicEntry> out; std::vector<BasicEntry> out;
@ -74,7 +104,7 @@ std::vector<BasicEntry> MakeEntires(std::string filename) {
} else { } else {
if ( (linenum - 15) % 3 == 0) { if ( (linenum - 15) % 3 == 0) {
line1 = line; line1 = line;
if (line == "</td></tr></tbody></table>") break; if (line == "</td></tr></tbody></table>" || line == "</TABLE>" ) break;
} else if ( (linenum - 15) % 3 == 1) { } else if ( (linenum - 15) % 3 == 1) {
line2 = line; line2 = line;
@ -92,25 +122,36 @@ std::vector<BasicEntry> MakeEntires(std::string filename) {
auto secondslash = line1.find("/", firstslash+1); auto secondslash = line1.find("/", firstslash+1);
auto thirdslash = line1.find("/", secondslash+1); auto thirdslash = line1.find("/", secondslash+1);
auto firstpar = line1.find("(", thirdslash+1);
auto secondpar = line1.find(")", firstpar+1);
auto p1class = line1.substr(firstslash+1, secondslash - firstslash - 1); auto p1class = line1.substr(firstslash+1, secondslash - firstslash - 1);
auto p1name = line1.substr(secondslash+1, thirdslash - secondslash -1); auto p1name = line1.substr(secondslash+1, thirdslash - secondslash -1);
auto p1match = line1.substr(firstpar+1, secondpar - firstpar - 2);
std::cout << p1match << std::endl;
firstquote = line2.find("\""); firstquote = line2.find("\"");
secondquote = line2.find("\"", firstquote+1); secondquote = line2.find("\"", firstquote+1);
firstslash = line2.find("/", secondquote+1); firstslash = line2.find("/", secondquote+1);
secondslash = line2.find("/", firstslash+1); secondslash = line2.find("/", firstslash+1);
thirdslash = line2.find("/", secondslash+1); thirdslash = line2.find("/", secondslash+1);
firstpar = line2.find("(", thirdslash+1);
secondpar = line2.find(")", firstpar+1);
auto p2class = line2.substr(firstslash+1, secondslash - (firstslash+1)); auto p2class = line2.substr(firstslash+1, secondslash - (firstslash+1));
auto p2name = line2.substr(secondslash+1, thirdslash - (secondslash+1)); auto p2name = line2.substr(secondslash+1, thirdslash - (secondslash+1));
auto p2match = line2.substr(firstpar+1, secondpar - firstpar - 2);
std::cout << p2match << std::endl;
auto p1 = Person(p1class, p1name); auto p1 = Person(p1class, p1name);
auto p2 = Person(p2class, p2name); auto p2 = Person(p2class, p2name);
printf("%s\n", p2class.c_str());
BasicEntry finent = {.A = p1, .B = p2, .matchlink = matchlink}; BasicEntry finent = {.A = p1, .B = p2, .matchlink = matchlink, .Apercent = std::stoi(p1match), .Bpercent = std::stoi(p2match) };
out.push_back(finent); out.push_back(finent);
@ -127,44 +168,88 @@ struct State {
}; };
void changelayout(Fl_Widget * w, void * meow) {
std::pair<Fl_Flex&, Fl_Multi_Browser&> * in = (std::pair<Fl_Flex&, Fl_Multi_Browser&>* ) meow;
in->second.show();
// in->second.parent()->redraw();
// in->first.window()->redraw();
//in->first.init_sizes();
in->first.layout();
//in->first.redraw();
}
int main (int argc, char ** argv) { int main (int argc, char ** argv) {
if (argc < 2) { if (argc < 2) {
std::cout << "Not enough args" << std::endl; std::cout << "Not enough args" << std::endl;
exit(1); exit(1);
} }
State s; State s;
s.entries = MakeEntires(argv[1]); s.entries = MakeEntires(argv[1]);
for (auto e : s.entries) { for (auto e : s.entries) {
std::cout << e << std::endl; std::cout << e << std::endl;
} }
Fl::scheme("base");
auto window = std::make_unique<Fl_Window>(300, 300, 300, 300, "MossMan :D"); auto window = std::make_unique<Fl_Window>(300, 300, 300, 300, "MossMan :D");
auto group = std::make_unique<Fl_Group>(0,0,300,300); auto group = std::make_unique<Fl_Group>(0,0,300,300);
auto group2 = std::make_unique<Fl_Group>(0, 0, 300, 50);
auto box = std::make_unique<Fl_Box>(0,0,100,50,"MossMan"); auto box = std::make_unique<Fl_Box>(0,0,100,50,"MossMan");
box->labelsize(36); box->labelsize(36);
box->labelfont(FL_TIMES | FL_BOLD); box->labelfont(FL_TIMES | FL_BOLD);
box->align(FL_ALIGN_INSIDE | FL_ALIGN_TOP_LEFT); box->align(FL_ALIGN_INSIDE | FL_ALIGN_TOP_LEFT);
auto browser = std::make_unique<Fl_Multi_Browser>(0,51,300,250); auto button = std::make_unique<Fl_Button>(250, 0, 50, 50);
auto button2 = std::make_unique<Fl_Button>(200,0, 50, 50);
group2->resizable(*box);
group2->end();
auto group3 = std::make_unique<Fl_Flex>(0,51,300, 250, Fl_Flex::HORIZONTAL);
// auto browser = std::make_unique<Fl_Multi_Browser>(0,51,300,250);
// auto browser2 = std::make_unique<Fl_Multi_Browser>(0,51,300,250);
auto browser = std::make_unique<Fl_Multi_Browser>(0,0,0,0);
auto browser2 = std::make_unique<Fl_Multi_Browser>(0,0,0,0);
browser2->hide();
group3->end();
std::pair<Fl_Flex&, Fl_Multi_Browser&> saved(*group3, *browser2);
button2->callback(changelayout,&saved);
auto icon = std::make_unique<Fl_PNG_Image>("Inspect", icon_inspect_file_png, icon_inspect_file_png_len);
button->image(*icon);
button->tooltip("Inspect Entr(ies)");
for (auto e : s.entries) { for (auto e : s.entries) {
auto h = ((e.A.year + "/" + e.A.name) + " and " + (e.B.year + "/" + e.B.name)); auto h = ((e.A.year + "/" + e.A.name) + " and " + (e.B.year + "/" + e.B.name) + " (" + std::to_string(e.Apercent) + "%, " + std::to_string(e.Bpercent) + "%)");
browser->add(h.c_str()); browser->add(h.c_str());
} }
group->resizable(*browser); group->resizable(*group3);
group->end(); group->end();
window->resizable(*group); window->resizable(*group);
window->end(); window->end();
Selected callbackdata(*browser);
button->callback(show_callback, (void*) &callbackdata);
window->show(); window->show();
return Fl::run(); return Fl::run();
} }