Initial commit. Added old code. Added README
This commit is contained in:
commit
0102605c07
9
Makefile
Normal file
9
Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
all:
|
||||||
|
make mindgen
|
||||||
|
make watcher
|
||||||
|
|
||||||
|
mindgen:
|
||||||
|
g++ MindNode.cpp mindgen_funcs.cpp mindgen.cpp -o mindgen
|
||||||
|
|
||||||
|
watcher:
|
||||||
|
gcc watcher.c -o watcher
|
||||||
110
MindNode.cpp
Normal file
110
MindNode.cpp
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
|
#include "MindNode.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
MindNode::MindNode()
|
||||||
|
: m_parent(NULL), m_first_child(NULL), m_next_node(NULL), m_id(""),
|
||||||
|
m_text(""), m_link(""), m_icons()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MindNode::~MindNode()
|
||||||
|
{
|
||||||
|
MindNode* curr_child;
|
||||||
|
MindNode* next_child;
|
||||||
|
|
||||||
|
curr_child = m_first_child;
|
||||||
|
while (NULL != curr_child)
|
||||||
|
{
|
||||||
|
next_child = curr_child->m_next_node;
|
||||||
|
delete curr_child;
|
||||||
|
curr_child = next_child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MindNode*
|
||||||
|
MindNode::getParent() const
|
||||||
|
{
|
||||||
|
return m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
MindNode*
|
||||||
|
MindNode::getFirstChild() const
|
||||||
|
{
|
||||||
|
return m_first_child;
|
||||||
|
}
|
||||||
|
|
||||||
|
MindNode*
|
||||||
|
MindNode::getNextNode() const
|
||||||
|
{
|
||||||
|
return m_next_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
MindNode::getID() const
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
MindNode::getText() const
|
||||||
|
{
|
||||||
|
return m_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
string
|
||||||
|
MindNode::getLink() const
|
||||||
|
{
|
||||||
|
return m_link;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<string>
|
||||||
|
MindNode::getIcons() const
|
||||||
|
{
|
||||||
|
return m_icons;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MindNode::setParent(MindNode* parent)
|
||||||
|
{
|
||||||
|
m_parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MindNode::setFirstChild(MindNode* first_child)
|
||||||
|
{
|
||||||
|
m_first_child = first_child;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MindNode::setNextNode(MindNode* next_node)
|
||||||
|
{
|
||||||
|
m_next_node = next_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MindNode::setID(string& id)
|
||||||
|
{
|
||||||
|
m_id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MindNode::setText(string& text)
|
||||||
|
{
|
||||||
|
m_text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MindNode::setLink(string& link)
|
||||||
|
{
|
||||||
|
m_link = link;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MindNode::addIcon(string& icon)
|
||||||
|
{
|
||||||
|
m_icons.push_back(icon);
|
||||||
|
}
|
||||||
58
MindNode.h
Normal file
58
MindNode.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#ifndef MIND_NODE_H_
|
||||||
|
#define MIND_NODE_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
class MindNode
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
// The parent of this node in the tree
|
||||||
|
MindNode* m_parent;
|
||||||
|
|
||||||
|
// The first child of this node in the tree
|
||||||
|
MindNode* m_first_child;
|
||||||
|
|
||||||
|
// The next node with the same parent in the tree
|
||||||
|
MindNode* m_next_node;
|
||||||
|
|
||||||
|
// ID of the node
|
||||||
|
string m_id;
|
||||||
|
|
||||||
|
// Content of the node
|
||||||
|
string m_text;
|
||||||
|
|
||||||
|
// Link of the node
|
||||||
|
string m_link;
|
||||||
|
|
||||||
|
// Array of all icons in this node
|
||||||
|
vector<string> m_icons;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Default Constructor & Destructor
|
||||||
|
MindNode();
|
||||||
|
~MindNode();
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
MindNode* getParent() const;
|
||||||
|
MindNode* getFirstChild() const;
|
||||||
|
MindNode* getNextNode() const;
|
||||||
|
string getID() const;
|
||||||
|
string getText() const;
|
||||||
|
string getLink() const;
|
||||||
|
vector<string> getIcons() const;
|
||||||
|
|
||||||
|
// Setters
|
||||||
|
void setParent(MindNode* _parent);
|
||||||
|
void setFirstChild(MindNode* _first_child);
|
||||||
|
void setNextNode(MindNode* _next_node);
|
||||||
|
void setID(string& _id);
|
||||||
|
void setText(string& _text);
|
||||||
|
void setLink(string& _link);
|
||||||
|
void addIcon(string& _icon);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // MIND_NODE_H_
|
||||||
19
README
Normal file
19
README
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# How to use
|
||||||
|
### Preparation
|
||||||
|
You will need 2 folders
|
||||||
|
|
||||||
|
1. In the "source" folder you will add/modify/remove FreeMind .mm files
|
||||||
|
Please do not use it for anything else.
|
||||||
|
|
||||||
|
2. In the "destination" folder will be automatically generated/delete html files.
|
||||||
|
If the source file is named "map.mm" then the resulting html file will be "map.mm.html".
|
||||||
|
The "files.zip" must be unpacked in the "destination" folder such that there is a single level "files" folder.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
Invoke the "watcher" executable from a directory where the "mindgen" is located (usually the same one)
|
||||||
|
```
|
||||||
|
./watcher /path/to/src /path/to/dst
|
||||||
|
```
|
||||||
|
|
||||||
|
### command.sh
|
||||||
|
Example script that automatically changes the working directory to its location and executes the watcher
|
||||||
3
command.sh
Executable file
3
command.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
cd "${BASH_SOURCE%/*}/"
|
||||||
|
./watcher ../src/ ../dst/ &
|
||||||
56
mindgen.cpp
Normal file
56
mindgen.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "mindgen_funcs.h"
|
||||||
|
#include "MindNode.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
void printTree(MindNode* root)
|
||||||
|
{/*
|
||||||
|
if (root != NULL)
|
||||||
|
{
|
||||||
|
cout << "ID: " << root->getID() << endl;
|
||||||
|
cout << "TEXT: " << root->getText() << endl;
|
||||||
|
cout << "LINK: " << root->getLink() << endl;
|
||||||
|
vector<string> vec = root->getIcons();
|
||||||
|
for (vector<string>::iterator it = vec.begin(); it != vec.end(); ++it)
|
||||||
|
{
|
||||||
|
cout << "ICON: " << *it << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "DOWN" << endl;
|
||||||
|
printTree(root->getFirstChild());
|
||||||
|
|
||||||
|
cout << "RIGHT" << endl;
|
||||||
|
printTree(root->getNextNode());
|
||||||
|
}
|
||||||
|
cout << "UP" << endl;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
ifstream input_file;
|
||||||
|
ofstream output_file;
|
||||||
|
MindNode* root;
|
||||||
|
|
||||||
|
if (argc < 3)
|
||||||
|
{
|
||||||
|
cout << "Usage: " << argv[0] << " [mindmap] [output]" << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
input_file.open(argv[1]);
|
||||||
|
output_file.open(argv[2]);
|
||||||
|
|
||||||
|
if (0 != parse_mindmap(input_file, &root))
|
||||||
|
{
|
||||||
|
cout << "ERR" << endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printTree(root);
|
||||||
|
|
||||||
|
write_html(output_file, root);
|
||||||
|
delete root;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
344
mindgen_funcs.cpp
Normal file
344
mindgen_funcs.cpp
Normal file
@ -0,0 +1,344 @@
|
|||||||
|
#include <cctype>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "mindgen_funcs.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
struct tag_struct
|
||||||
|
{
|
||||||
|
string name;
|
||||||
|
map<string, string> params;
|
||||||
|
bool is_closed;
|
||||||
|
bool is_closing;
|
||||||
|
};
|
||||||
|
|
||||||
|
void indent(ostream& _out, int _count);
|
||||||
|
void write_initial_html(ostream& _out, int _part);
|
||||||
|
void write_node_recursive(ostream& _out, const MindNode* _root, int _indent_count);
|
||||||
|
void get_tag(istream& _in, string& _content);
|
||||||
|
void generate_map(string& _content, tag_struct& _tag);
|
||||||
|
|
||||||
|
// DEFININTIONS
|
||||||
|
void
|
||||||
|
indent(ostream& out, int count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
out << "\t";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
write_initial_html(ostream& out, int part)
|
||||||
|
{
|
||||||
|
switch (part)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;
|
||||||
|
out << "<?xml-stylesheet href=\"files/treestyles.css\" type=\"text/css\"?>" << endl;
|
||||||
|
out << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">" << endl;
|
||||||
|
out << "<html xmlns=\"http://www.w3.org/1999/xhtml\">" << endl;
|
||||||
|
out << "\t<head>" << endl;
|
||||||
|
out << "\t\t<meta content=\"text/html; charset=UTF-8\" http-equiv=\"Content-Type\" />" << endl;
|
||||||
|
out << "\t\t<title>";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
out << "</title>" << endl;
|
||||||
|
out << "\t\t<link rel=\"stylesheet\" href=\"files/treestyles.css\" type=\"text/css\" />" << endl;
|
||||||
|
out << "\t\t<script type=\"text/javascript\" src=\"files/marktree.js\"></script>" << endl;
|
||||||
|
out << "\t</head>" << endl;
|
||||||
|
out << "\t<body>" << endl;
|
||||||
|
out << "\t\t<div class=\"basetop\">" << endl;
|
||||||
|
out << "\t\t\t<a onclick=\"expandAll(document.getElementById('base'))\" href=\"#\">Expand</a>" << endl;
|
||||||
|
out << "\t\t\t-" << endl;
|
||||||
|
out << "\t\t\t<a onclick=\"collapseAll(document.getElementById('base'))\" href=\"#\">Collapse</a>" << endl;
|
||||||
|
out << "\t\t</div>" << endl;
|
||||||
|
out << "\t\t<div class=\"basetext\" id=\"base\">" << endl;
|
||||||
|
out << "\t\t\t<ul>" << endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
out << "\t\t\t</ul>" << endl;
|
||||||
|
out << "\t\t</div>" << endl;
|
||||||
|
out << "\t</body>" << endl;
|
||||||
|
out << "</html>" << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
write_node_recursive(ostream& out, const MindNode* root, int indent_count)
|
||||||
|
{
|
||||||
|
while (NULL != root)
|
||||||
|
{
|
||||||
|
indent(out, indent_count);
|
||||||
|
if (NULL == root->getFirstChild())
|
||||||
|
{
|
||||||
|
out << "<li class=\"basic\" id=\"FM" << root->getID() << "FM\">" << endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out << "<li class=\"col\" id=\"FM" << root->getID() << "FM\">" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are icons - print them
|
||||||
|
if (!root->getIcons().empty())
|
||||||
|
{
|
||||||
|
vector<string> icons = root->getIcons();
|
||||||
|
for (vector<string>::iterator it = icons.begin(); it != icons.end(); ++it)
|
||||||
|
{
|
||||||
|
indent(out, indent_count + 1);
|
||||||
|
out << "<img src=\"files/icons/" << *it << ".png\"/>" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
indent(out, indent_count + 1);
|
||||||
|
out << "<div class=\"nodecontent\">" << endl;
|
||||||
|
|
||||||
|
indent(out, indent_count + 2);
|
||||||
|
if (!root->getLink().empty())
|
||||||
|
{
|
||||||
|
out << "<a href=\"" << root->getLink() << "\">";
|
||||||
|
}
|
||||||
|
|
||||||
|
out << root->getText();
|
||||||
|
|
||||||
|
if (!root->getLink().empty())
|
||||||
|
{
|
||||||
|
out << "</a>" << endl;
|
||||||
|
indent(out, indent_count + 2);
|
||||||
|
out << "<a href=\"" << root->getLink() << "\">" << endl;
|
||||||
|
|
||||||
|
indent(out, indent_count + 3);
|
||||||
|
out << "<img src=\"files/ilink.png\" style=\"border-width:0\" />" << endl;
|
||||||
|
|
||||||
|
indent(out, indent_count + 2);
|
||||||
|
out << "</a>";
|
||||||
|
}
|
||||||
|
|
||||||
|
out << endl;
|
||||||
|
|
||||||
|
indent(out, indent_count + 1);
|
||||||
|
out << "</div>" << endl;
|
||||||
|
|
||||||
|
if (NULL != root->getFirstChild())
|
||||||
|
{
|
||||||
|
indent(out, indent_count + 1);
|
||||||
|
out << "<ul class=\"subexp\">" << endl;
|
||||||
|
write_node_recursive(out, root->getFirstChild(), indent_count + 2);
|
||||||
|
|
||||||
|
indent(out, indent_count + 1);
|
||||||
|
out << "</ul>" << endl;
|
||||||
|
}
|
||||||
|
indent(out, indent_count);
|
||||||
|
out << "</li>" << endl;
|
||||||
|
|
||||||
|
root = root->getNextNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
get_tag(istream& in, string& content)
|
||||||
|
{
|
||||||
|
char symbol;
|
||||||
|
|
||||||
|
in.get(symbol);
|
||||||
|
while ('>' != symbol)
|
||||||
|
{
|
||||||
|
content += symbol;
|
||||||
|
in.get(symbol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
generate_map(string& content, tag_struct& tag)
|
||||||
|
{
|
||||||
|
size_t index;
|
||||||
|
string name;
|
||||||
|
string value;
|
||||||
|
|
||||||
|
tag.params.clear();
|
||||||
|
tag.name.clear();
|
||||||
|
tag.is_closed = false;
|
||||||
|
tag.is_closing = false;
|
||||||
|
|
||||||
|
// Removes header / trailer slashes and skips comments
|
||||||
|
if ('/' == content[0])
|
||||||
|
{
|
||||||
|
tag.is_closing = true;
|
||||||
|
content.erase(0, 1);
|
||||||
|
}
|
||||||
|
if ('/' == content[content.size() - 1])
|
||||||
|
{
|
||||||
|
tag.is_closed = true;
|
||||||
|
content.erase(content.size() - 1, 1);
|
||||||
|
}
|
||||||
|
if ('!' == content[0])
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First word is the name
|
||||||
|
index = content.find(' ');
|
||||||
|
tag.name = content.substr(0, index);
|
||||||
|
if (string::npos == index)
|
||||||
|
{
|
||||||
|
content.clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
content.erase(0, index + 1);
|
||||||
|
}
|
||||||
|
// If we have more than just a name
|
||||||
|
while (!content.empty())
|
||||||
|
{
|
||||||
|
index = content.find('=');
|
||||||
|
name = content.substr(0, index);
|
||||||
|
content.erase(0, index + 2);
|
||||||
|
|
||||||
|
index = content.find('"');
|
||||||
|
value = content.substr(0, index);
|
||||||
|
content.erase(0, index + 1);
|
||||||
|
tag.params.insert(pair<string, string>(name, value));
|
||||||
|
if (!content.empty())
|
||||||
|
{
|
||||||
|
content.erase(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HEADER FUNCS
|
||||||
|
|
||||||
|
int
|
||||||
|
parse_mindmap(istream& in, MindNode** root)
|
||||||
|
{
|
||||||
|
char parse = '\0';
|
||||||
|
string search;
|
||||||
|
string content;
|
||||||
|
tag_struct current_tag;
|
||||||
|
|
||||||
|
MindNode* current_node = NULL;
|
||||||
|
|
||||||
|
while (!in.eof())
|
||||||
|
{
|
||||||
|
// Find Next Tag
|
||||||
|
in.get(parse);
|
||||||
|
while ((parse != '<') && (!in.eof()))
|
||||||
|
{
|
||||||
|
in.get(parse);
|
||||||
|
}
|
||||||
|
if (in.eof())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
content = "";
|
||||||
|
get_tag(in, content);
|
||||||
|
generate_map(content, current_tag);
|
||||||
|
|
||||||
|
// Map parse
|
||||||
|
|
||||||
|
if ("map" == current_tag.name)
|
||||||
|
{
|
||||||
|
if (NULL != current_node)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node Parse
|
||||||
|
if ("node" == current_tag.name)
|
||||||
|
{
|
||||||
|
if (current_tag.is_closing)
|
||||||
|
{
|
||||||
|
current_node = current_node->getParent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MindNode* node_new = new MindNode();
|
||||||
|
|
||||||
|
node_new->setID(current_tag.params.find("ID")->second);
|
||||||
|
|
||||||
|
if (current_tag.params.end() != current_tag.params.find("TEXT"))
|
||||||
|
{
|
||||||
|
node_new->setText(current_tag.params.find("TEXT")->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_tag.params.end() != current_tag.params.find("LINK"))
|
||||||
|
{
|
||||||
|
node_new->setLink(current_tag.params.find("LINK")->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == current_node)
|
||||||
|
{
|
||||||
|
*root = node_new;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node_new->setParent(current_node);
|
||||||
|
|
||||||
|
if(NULL == current_node->getFirstChild())
|
||||||
|
{
|
||||||
|
current_node->setFirstChild(node_new);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MindNode* last_child = current_node->getFirstChild();
|
||||||
|
while(NULL != last_child->getNextNode())
|
||||||
|
{
|
||||||
|
last_child = last_child->getNextNode();
|
||||||
|
}
|
||||||
|
last_child->setNextNode(node_new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current_node = node_new;
|
||||||
|
|
||||||
|
if (current_tag.is_closed)
|
||||||
|
{
|
||||||
|
current_node = current_node->getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("icon" == current_tag.name)
|
||||||
|
{
|
||||||
|
if (current_tag.params.end() != current_tag.params.find("BUILTIN"))
|
||||||
|
{
|
||||||
|
current_node->addIcon(current_tag.params.find("BUILTIN")->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
write_html(ostream& out, const MindNode* root)
|
||||||
|
{
|
||||||
|
if (NULL == root)
|
||||||
|
{
|
||||||
|
cerr << "Error at \"" << __FILE__ << "\" on line " << __LINE__ << endl;
|
||||||
|
cerr << "Root node is NULL" << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write first part html
|
||||||
|
write_initial_html(out, 0);
|
||||||
|
|
||||||
|
// Write title
|
||||||
|
out << root->getText();
|
||||||
|
|
||||||
|
// Write next part html
|
||||||
|
write_initial_html(out, 1);
|
||||||
|
|
||||||
|
// Write node structure
|
||||||
|
write_node_recursive(out, root, 4);
|
||||||
|
|
||||||
|
// Write last part html
|
||||||
|
write_initial_html(out, 2);
|
||||||
|
}
|
||||||
15
mindgen_funcs.h
Normal file
15
mindgen_funcs.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef MINDGEN_FUNCS_H_
|
||||||
|
#define MINDGEN_FUNCS_H_
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "MindNode.h"
|
||||||
|
|
||||||
|
using std::istream;
|
||||||
|
using std::ostream;
|
||||||
|
|
||||||
|
int parse_mindmap(istream& in, MindNode** root);
|
||||||
|
|
||||||
|
void write_html(ostream& out, const MindNode* root);
|
||||||
|
|
||||||
|
#endif // MINDGEN_FUNCS_H_
|
||||||
252
watcher.c
Normal file
252
watcher.c
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define POLL_TIME_SEC 60
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prints the usage string
|
||||||
|
*/
|
||||||
|
void usage(const char* _name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks if the filepath is a directory or not
|
||||||
|
*
|
||||||
|
* Returns -1 on error; 0 on false; 1 on true
|
||||||
|
*/
|
||||||
|
int is_dir(const char* _filepath);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Executes the generation command
|
||||||
|
*
|
||||||
|
* Returns -1 on error;
|
||||||
|
*/
|
||||||
|
int execute_mindgen();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Executes the deletion command
|
||||||
|
*
|
||||||
|
* Returns -1 on error;
|
||||||
|
*/
|
||||||
|
int execute_delete(const char* _dir, const char* _filename);
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
int notify_fd;
|
||||||
|
int watch_fd;
|
||||||
|
int error;
|
||||||
|
bool deleted;
|
||||||
|
unsigned int buffer_size;
|
||||||
|
char* buffer;
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
// [name] [watch dir] [destination dir]
|
||||||
|
if (argc < 3)
|
||||||
|
{
|
||||||
|
usage(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check dirs and permissions
|
||||||
|
if (1 != is_dir(argv[1]))
|
||||||
|
{
|
||||||
|
usage(argv[0]);
|
||||||
|
printf("Watch directory is not a folder, does not exist or there are not sufficient permissions.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 != is_dir(argv[2]))
|
||||||
|
{
|
||||||
|
usage(argv[0]);
|
||||||
|
printf("Destination directory is not a folder, does not exist or there are not sufficient permissions.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// inotify init
|
||||||
|
notify_fd = inotify_init();
|
||||||
|
if (notify_fd < 0)
|
||||||
|
{
|
||||||
|
printf("BAD NOTIFY FD\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// inotify add watch
|
||||||
|
watch_fd = inotify_add_watch(notify_fd, argv[1], IN_DELETE | IN_DELETE_SELF | IN_CLOSE_WRITE);
|
||||||
|
if (watch_fd < 0)
|
||||||
|
{
|
||||||
|
printf("BAD WATCH FD\n");
|
||||||
|
close(notify_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleted = false;
|
||||||
|
while (!deleted)
|
||||||
|
{
|
||||||
|
// wait for event
|
||||||
|
buffer_size = 0;
|
||||||
|
while (0 == buffer_size)
|
||||||
|
{
|
||||||
|
sleep(POLL_TIME_SEC);
|
||||||
|
error = ioctl(notify_fd, FIONREAD, &buffer_size);
|
||||||
|
if (0 != error)
|
||||||
|
{
|
||||||
|
printf("BAD IOCTL\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create big enough buffer and read all data
|
||||||
|
buffer = (char*)malloc(buffer_size);
|
||||||
|
error = read(notify_fd, buffer, buffer_size);
|
||||||
|
if (error != buffer_size)
|
||||||
|
{
|
||||||
|
printf("BAD BUFFER SIZE\n");
|
||||||
|
free(buffer);
|
||||||
|
close(notify_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read and process all events
|
||||||
|
offset = 0;
|
||||||
|
while (offset < buffer_size)
|
||||||
|
{
|
||||||
|
struct inotify_event* event = (struct inotify_event*)(buffer + offset);
|
||||||
|
|
||||||
|
// on create/modify - mindgen
|
||||||
|
if (0 != (event->mask & IN_CLOSE_WRITE))
|
||||||
|
{
|
||||||
|
//printf("FILE WRITTEN TO: %s\n", event->name);
|
||||||
|
execute_mindgen(argv[2], event->name, argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// on delete - rm
|
||||||
|
if (0 != (event->mask & IN_DELETE))
|
||||||
|
{
|
||||||
|
//printf("DELETE: %s\n", event->name);
|
||||||
|
execute_delete(argv[2], event->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// on delete_self - exit
|
||||||
|
if (0 != (event->mask & IN_DELETE_SELF))
|
||||||
|
{
|
||||||
|
printf("Watched folder deleted. Stopping.\n");
|
||||||
|
deleted = true;
|
||||||
|
}
|
||||||
|
offset += sizeof(struct inotify_event) + event->len;
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
buffer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(const char* name)
|
||||||
|
{
|
||||||
|
if (NULL == name)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s watch_dir dest_dir\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
is_dir(const char* filepath)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
struct stat file_stat;
|
||||||
|
|
||||||
|
if (NULL == filepath)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
result = stat(filepath, &file_stat);
|
||||||
|
if (0 == result)
|
||||||
|
{
|
||||||
|
if (S_ISDIR(file_stat.st_mode))
|
||||||
|
{
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int execute_mindgen(const char* dest_dir, const char* filename, const char* source_dir)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
int child_status;
|
||||||
|
char source_fullname[strlen(source_dir) + strlen(filename) + 2];
|
||||||
|
char dest_fullname[strlen(source_dir) + strlen(filename) + 7];
|
||||||
|
char* arglist[4];
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid < 0)
|
||||||
|
{
|
||||||
|
printf("Error trying to generate html.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (0 == pid)
|
||||||
|
{
|
||||||
|
strcpy(source_fullname, source_dir);
|
||||||
|
strcat(source_fullname, "/");
|
||||||
|
strcat(source_fullname, filename);
|
||||||
|
|
||||||
|
strcpy(dest_fullname, dest_dir);
|
||||||
|
strcat(dest_fullname, "/");
|
||||||
|
strcat(dest_fullname, filename);
|
||||||
|
strcat(dest_fullname, ".html");
|
||||||
|
|
||||||
|
arglist[0] = "mindgen";
|
||||||
|
arglist[1] = source_fullname;
|
||||||
|
arglist[2] = dest_fullname;
|
||||||
|
arglist[3] = NULL;
|
||||||
|
//printf("%s %s %s\n", arglist[0], arglist[1], arglist[2]);
|
||||||
|
execv("./mindgen", arglist);
|
||||||
|
|
||||||
|
printf("Error generating html.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
wait(&child_status);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int execute_delete(const char* dir, const char* filename)
|
||||||
|
{
|
||||||
|
int pid;
|
||||||
|
int child_status;
|
||||||
|
char fullname[strlen(dir) + strlen(filename) + 7];
|
||||||
|
char* arglist[3];
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid < 0)
|
||||||
|
{
|
||||||
|
printf("Error trying to delete.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (0 == pid)
|
||||||
|
{
|
||||||
|
strcpy(fullname, dir);
|
||||||
|
strcat(fullname, "/");
|
||||||
|
strcat(fullname, filename);
|
||||||
|
strcat(fullname, ".html");
|
||||||
|
|
||||||
|
arglist[0] = "rm";
|
||||||
|
arglist[1] = fullname;
|
||||||
|
arglist[2] = NULL;
|
||||||
|
//printf("%s %s\n", arglist[0], arglist[1]);
|
||||||
|
execv("/bin/rm", arglist);
|
||||||
|
|
||||||
|
printf("Error deleting.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
wait(&child_status);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user