utf8 len
This commit is contained in:
@@ -2,8 +2,6 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
typedef char C8;
|
||||
|
||||
typedef int8_t I8;
|
||||
typedef uint8_t U8;
|
||||
typedef int16_t I16;
|
||||
|
||||
@@ -7,7 +7,7 @@ using std::cin;
|
||||
using std::cout;
|
||||
int main()
|
||||
{
|
||||
setlocale(LC_ALL, ""); /* TODO: set to utf */
|
||||
setlocale(LC_ALL, "en_US.UTF-8");
|
||||
|
||||
/* Init ncurses */
|
||||
initscr(); /* Start curses mode */
|
||||
|
||||
+13
-3
@@ -1,5 +1,6 @@
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
#include<ctype.h>
|
||||
#include <ncursesw/ncurses.h>
|
||||
|
||||
#include"person.h"
|
||||
@@ -90,10 +91,10 @@ void Person::save(std::ofstream &file)const
|
||||
|
||||
void Person::load(std::ifstream &file)
|
||||
{
|
||||
char nameLen;
|
||||
U8 nameLen;
|
||||
file.read((char*)&nameLen, sizeof(nameLen)); //Check len
|
||||
|
||||
C8 nameBuf[128];
|
||||
char nameBuf[128];
|
||||
file.read(nameBuf, nameLen * sizeof(*nameBuf));
|
||||
nameBuf[nameLen] = '\0';
|
||||
name_ = nameBuf;
|
||||
@@ -139,9 +140,18 @@ bool Person::isMale() const
|
||||
return isMale_;
|
||||
}
|
||||
|
||||
static U16 strUtf8Symbols(const std::string& str)
|
||||
{
|
||||
U16 num = 0;
|
||||
for(char c: str)
|
||||
num += ((c & 0xC0) != 0x80);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
U16 Person::boxWidth() const
|
||||
{
|
||||
return name_.size() + 4; /* TODO: get actual lenght */
|
||||
return strUtf8Symbols(name_) + 4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,3 +11,13 @@ Color
|
||||
Partialy visible people
|
||||
Scrolling
|
||||
Zooming
|
||||
|
||||
Visualization:
|
||||
- proper horizontal navigation
|
||||
|
||||
Compilation
|
||||
- static and dynamic ncurses
|
||||
|
||||
?
|
||||
- same person can be present twice
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ Tree Tree::operator+ (const Tree& other)//
|
||||
{
|
||||
for (unsigned j = 0; j < other.people[i].numRel_; ++j) //Adds the number of relatives from the II to the number in the I
|
||||
{
|
||||
if(newId[other.relations[i][j].id] > numPeople)
|
||||
if (newId[other.relations[i][j].id] > numPeople)
|
||||
++result.people[newId[i]].numRel_;
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ void Tree::rename(const char* newName)
|
||||
treeName = newName;
|
||||
}
|
||||
|
||||
unsigned Tree::findId(const char* name, const short year, const unsigned char month, const unsigned char day)const
|
||||
person_id Tree::findId(const char* name, const short year, const unsigned char month, const unsigned char day) const
|
||||
{
|
||||
//TODO
|
||||
//Person sought(name, day, month, year,)
|
||||
@@ -159,7 +159,7 @@ unsigned Tree::findId(const char* name, const short year, const unsigned char mo
|
||||
return Nobody;
|
||||
}
|
||||
|
||||
unsigned Tree::findOldestAncestor(unsigned id, bool isMale)const
|
||||
person_id Tree::findOldestAncestor(unsigned id, bool isMale)const
|
||||
{
|
||||
for (unsigned i = 0; i < people[id].numRel_; ++i)
|
||||
{
|
||||
@@ -169,33 +169,58 @@ unsigned Tree::findOldestAncestor(unsigned id, bool isMale)const
|
||||
return id;
|
||||
}
|
||||
|
||||
unsigned Tree::findCommonAncestor(const unsigned firstId, const unsigned secondId)const
|
||||
person_id Tree::findCommonAncestor(const unsigned firstId, const unsigned secondId) const
|
||||
{
|
||||
vector<char> visited(numPeople); //if a member is visited twice he's a common ancestor
|
||||
for (unsigned i = 0; i < numPeople; ++i)
|
||||
visited[i] = 0;
|
||||
vector<U8> visited(numPeople); //if a member is visited twice he's a common ancestor
|
||||
|
||||
commonAncestorRec(firstId, visited);
|
||||
commonAncestorRec(secondId, visited);
|
||||
|
||||
unsigned oldestId = Nobody;
|
||||
person_id oldest = Nobody;
|
||||
U16 oldestBday = SHRT_MAX;
|
||||
for (unsigned i = 0; i < numPeople; ++i)
|
||||
for (person_id i = 0; i < numPeople; ++i)
|
||||
{
|
||||
if (visited[i] == 2 && people[i].birth_.year < oldestBday)
|
||||
{
|
||||
oldestBday = people[i].birth_.year;
|
||||
oldestId = i;
|
||||
oldest = i;
|
||||
}
|
||||
}
|
||||
return oldestId;
|
||||
return oldest;
|
||||
}
|
||||
|
||||
person_id Tree::findParent(person_id child, bool isParentMale) const
|
||||
{
|
||||
person_id parent = Nobody;
|
||||
for(const Relation& rel: relations[child])
|
||||
{
|
||||
if (rel.type == Child && people[rel.id].isMale())
|
||||
parent = rel.id;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
person_id Tree::findSpouse(person_id person) const
|
||||
{
|
||||
person_id spouse = Nobody;
|
||||
for(const Relation& rel: relations[person])
|
||||
{
|
||||
if (rel.type == Spouse)
|
||||
{
|
||||
spouse = rel.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return spouse;
|
||||
}
|
||||
|
||||
|
||||
/* person_id Tree::findRelation(person_id first, person_id second) const */
|
||||
/* { */
|
||||
/* const auto& curRels = relations[first]; */
|
||||
/* for(auto i =0; i<curRels.size(); ++i) */
|
||||
/* { */
|
||||
/* if(curRels[i].id == second) */
|
||||
/* if (curRels[i].id == second) */
|
||||
/* { */
|
||||
|
||||
/* } */
|
||||
@@ -392,12 +417,18 @@ void Tree::display()
|
||||
case KEY_UP:
|
||||
selectUp();
|
||||
break;
|
||||
case 'h':
|
||||
selectLeft();
|
||||
break;
|
||||
case 'j':
|
||||
selectDown();
|
||||
break;
|
||||
case 'k':
|
||||
selectUp();
|
||||
break;
|
||||
case 'l':
|
||||
selectRight();
|
||||
break;
|
||||
case 'i':
|
||||
people[selected_].displayInfo();
|
||||
draw();
|
||||
@@ -413,8 +444,8 @@ void Tree::draw() const
|
||||
erase(); //Clear the screen
|
||||
wnoutrefresh(stdscr);
|
||||
|
||||
U16 drawY = 0/* (LINES) / 2 */;
|
||||
U16 drawX = 0/* (COLS) / 2 */;
|
||||
I16 drawY = 0/* (LINES) / 2 */;
|
||||
I16 drawX = 0/* (COLS) / 2 */;
|
||||
drawLineWithWives(focused_, drawY, drawX);
|
||||
|
||||
doupdate();
|
||||
@@ -422,7 +453,7 @@ void Tree::draw() const
|
||||
|
||||
void Tree::print() const
|
||||
{
|
||||
for(auto& member: people)
|
||||
for(const Person& member: people)
|
||||
member.displayInfo();
|
||||
}
|
||||
|
||||
@@ -490,10 +521,12 @@ void Tree::printOldestAncestors(const unsigned id)const
|
||||
|
||||
|
||||
|
||||
void Tree::commonAncestorRec(person_id id, vector<char> &visited)const
|
||||
void Tree::commonAncestorRec(person_id id, vector<U8> &visited) const
|
||||
{
|
||||
++visited[id];
|
||||
|
||||
auto& curRels = relations[id];
|
||||
for (auto& rel: curRels)
|
||||
for (const Relation& rel: curRels)
|
||||
{
|
||||
if (rel.type == Child)
|
||||
{
|
||||
@@ -505,7 +538,7 @@ void Tree::commonAncestorRec(person_id id, vector<char> &visited)const
|
||||
|
||||
static U8 linkToFirstBorn(I16 startY, I16 startX, bool moreSiblings)
|
||||
{
|
||||
if(startY >= -2 && startX >= 0)
|
||||
if (startY >= -2 && startX >= 0)
|
||||
{
|
||||
WINDOW* win = newwin(3, 1, startY, startX); /* TODO: pad */
|
||||
|
||||
@@ -524,7 +557,7 @@ static U8 linkToChild(I16 startY, I16 startX, I16 endX, bool moreSiblings)
|
||||
{
|
||||
assert(endX >= startX);
|
||||
|
||||
if(startY >= -1 && endX >= 0)
|
||||
if (startY >= -1 && endX >= 0)
|
||||
{
|
||||
const I16 len = endX - startX;
|
||||
WINDOW* win = newwin(2, len, startY, startX);
|
||||
@@ -550,11 +583,11 @@ static U8 linkToChild(I16 startY, I16 startX, I16 endX, bool moreSiblings)
|
||||
/* std::vector<person_id> children; */
|
||||
/* for(U32 i=0; i<relations[id].size(); ++i) */
|
||||
/* { */
|
||||
/* if(relations[id][i].type == RelType::Parent) */
|
||||
/* if (relations[id][i].type == RelType::Parent) */
|
||||
/* children.push_back(relations[id][i].id); */
|
||||
/* } */
|
||||
|
||||
/* if(!children.empty()) */
|
||||
/* if (!children.empty()) */
|
||||
/* { */
|
||||
/* auto prevX = drawX; */
|
||||
/* drawY += BOX_HEIGHT; */
|
||||
@@ -583,10 +616,10 @@ I16 Tree::drawLineWithWives(const person_id id, I16 drawY, const I16 drawX) cons
|
||||
std::vector<person_id> children;
|
||||
for(const auto& rel: rels)
|
||||
{
|
||||
if(rel.type == RelType::Parent)
|
||||
if (rel.type == RelType::Parent)
|
||||
children.push_back(rel.id);
|
||||
|
||||
else if(rel.type == RelType::Spouse && spouse == Nobody)
|
||||
else if (rel.type == RelType::Spouse && spouse == Nobody)
|
||||
spouse = rel.id;
|
||||
}
|
||||
const size_t numKids = children.size();
|
||||
@@ -594,7 +627,7 @@ I16 Tree::drawLineWithWives(const person_id id, I16 drawY, const I16 drawX) cons
|
||||
id == selected_, spouse!=Nobody, false, numKids!=0);
|
||||
|
||||
U16 spouse_width = 0;
|
||||
if(spouse != Nobody)
|
||||
if (spouse != Nobody)
|
||||
{
|
||||
people[spouse].draw(drawY, drawX + person.boxWidth() + spouse_dist_,
|
||||
spouse == selected_, false, true);
|
||||
@@ -602,7 +635,7 @@ I16 Tree::drawLineWithWives(const person_id id, I16 drawY, const I16 drawX) cons
|
||||
}
|
||||
|
||||
auto childX = drawX;
|
||||
if(numKids!=0)
|
||||
if (numKids!=0)
|
||||
{
|
||||
auto prevX = childX;
|
||||
drawY += BOX_HEIGHT;
|
||||
@@ -624,26 +657,27 @@ I16 Tree::drawLineWithWives(const person_id id, I16 drawY, const I16 drawX) cons
|
||||
|
||||
void Tree::selectLeft() /* todo */
|
||||
{
|
||||
const auto& curRel = relations[selected_];
|
||||
|
||||
for(U32 i = 0; i < curRel.size(); ++i)
|
||||
if (findCommonAncestor(focused_, selected_) != Nobody) //if the selected is part of main tree
|
||||
{
|
||||
if(curRel[i].type == Sibling)
|
||||
{
|
||||
selected_ = curRel[i].id;
|
||||
draw();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
person_id spouse = findSpouse(selected_);
|
||||
selected_ = spouse;
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Tree::selectDown()
|
||||
{
|
||||
const auto& curRels = relations[selected_];
|
||||
|
||||
for(const auto& rel: curRels)
|
||||
for(const Relation& rel: curRels)
|
||||
{
|
||||
if(rel.type == Parent)
|
||||
if (rel.type == Parent)
|
||||
{
|
||||
selected_ = rel.id;
|
||||
draw();
|
||||
@@ -654,15 +688,40 @@ void Tree::selectDown()
|
||||
|
||||
void Tree::selectUp()
|
||||
{
|
||||
const auto& curRels = relations[selected_];
|
||||
person_id dad = Nobody, mom = Nobody;
|
||||
|
||||
for(const auto& rel: curRels)
|
||||
for(const Relation& rel: relations[selected_])
|
||||
{
|
||||
if(rel.type == Child && (people[rel.id].isMale() || rel.id == focused_))
|
||||
if (rel.type == Child)
|
||||
{
|
||||
selected_ = rel.id;
|
||||
draw();
|
||||
return;
|
||||
if (people[rel.id].isMale())
|
||||
dad = rel.id;
|
||||
else
|
||||
mom = rel.id;
|
||||
}
|
||||
}
|
||||
|
||||
if (mom == focused_ || (mom != Nobody && dad == Nobody))
|
||||
selected_ = mom;
|
||||
else if (dad != Nobody)
|
||||
selected_ = dad;
|
||||
|
||||
draw();
|
||||
}
|
||||
|
||||
void Tree::selectRight() /* todo */
|
||||
{
|
||||
if (findCommonAncestor(focused_, selected_) != Nobody) //if the selected is part of main tree
|
||||
{
|
||||
person_id spouse = findSpouse(selected_);
|
||||
if (spouse != Nobody)
|
||||
selected_ = spouse;
|
||||
else
|
||||
;
|
||||
draw();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,11 @@ public:
|
||||
|
||||
person_id findId(const char*, short year=0, const unsigned char month=0, const unsigned char day=0) const;
|
||||
person_id findOldestAncestor(person_id id, bool sex = 0) const;//
|
||||
person_id findCommonAncestor(person_id firstId, person_id secondId) const; //oldest common ancestor ID
|
||||
//oldest common ancestor ID, a person is considerd an ancestor of himself
|
||||
person_id findCommonAncestor(person_id firstId, person_id secondId) const;
|
||||
person_id findRelation(person_id first, person_id second) const;
|
||||
person_id findParent(person_id child, bool isParentMale) const;
|
||||
person_id findSpouse(person_id person) const;
|
||||
|
||||
void saveTree()const;//
|
||||
bool loadTree();
|
||||
@@ -58,7 +61,7 @@ public:
|
||||
void printOldestAncestors(person_id id)const;//
|
||||
|
||||
private:
|
||||
void commonAncestorRec(person_id id, std::vector<char> &visited)const;
|
||||
void commonAncestorRec(person_id id, std::vector<U8> &visited)const;
|
||||
|
||||
void draw() const;
|
||||
/* draw a line of people starting from person with id
|
||||
|
||||
Reference in New Issue
Block a user