From 25bcd2e22bd06df257e13ce1362a24a1fd440e79 Mon Sep 17 00:00:00 2001 From: Venelin Date: Mon, 16 Jan 2023 12:01:08 +0200 Subject: [PATCH] utf8 len --- common/basicTypes.h | 2 - main.cpp | 2 +- person.cpp | 16 ++++- todo.txt | 10 ++++ tree.cpp | 143 +++++++++++++++++++++++++++++++------------- tree.h | 7 ++- 6 files changed, 130 insertions(+), 50 deletions(-) diff --git a/common/basicTypes.h b/common/basicTypes.h index a2da5c4..efbec6d 100644 --- a/common/basicTypes.h +++ b/common/basicTypes.h @@ -2,8 +2,6 @@ #include -typedef char C8; - typedef int8_t I8; typedef uint8_t U8; typedef int16_t I16; diff --git a/main.cpp b/main.cpp index fa80d8e..9845db5 100644 --- a/main.cpp +++ b/main.cpp @@ -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 */ diff --git a/person.cpp b/person.cpp index 60c3e4a..f26ffed 100644 --- a/person.cpp +++ b/person.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #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; } diff --git a/todo.txt b/todo.txt index 1b84c02..e90c6bf 100644 --- a/todo.txt +++ b/todo.txt @@ -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 + diff --git a/tree.cpp b/tree.cpp index 07c6465..a324dc8 100644 --- a/tree.cpp +++ b/tree.cpp @@ -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 visited(numPeople); //if a member is visited twice he's a common ancestor - for (unsigned i = 0; i < numPeople; ++i) - visited[i] = 0; + vector 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 &visited)const +void Tree::commonAncestorRec(person_id id, vector &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 &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 children; */ /* for(U32 i=0; i 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 + { + + } } diff --git a/tree.h b/tree.h index 90229a9..c0bef58 100644 --- a/tree.h +++ b/tree.h @@ -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 &visited)const; + void commonAncestorRec(person_id id, std::vector &visited)const; void draw() const; /* draw a line of people starting from person with id