~ubuntu-branches/ubuntu/raring/notecase/raring

« back to all changes in this revision

Viewing changes to src/lib/FormatIOMMLX.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Nathan Handler
  • Date: 2008-12-21 13:09:58 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20081221130958-0ri77h0x7j1dclkq
Tags: 1.9.8-0ubuntu1
New upstream release (LP: #307752)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
////////////////////////////////////////////////////////////////////////////
2
 
// NoteCase notes manager project <http://notecase.sf.net>
3
 
//
4
 
// This code is licensed under BSD license.See "license.txt" for more details.
5
 
//
6
 
// File: Implements MM/LX Mindmap/Outline document format I/O (reading only)
7
 
////////////////////////////////////////////////////////////////////////////
8
 
 
9
 
#if _MSC_VER > 1000
10
 
  #pragma warning(disable: 4996)        //ignore deprecated functions warning
11
 
#endif
12
 
 
13
 
#include "FormatIOMMLX.h"
14
 
#include "DocumentIterator.h"
15
 
#include "debug.h"
16
 
#include "../config.h"
17
 
#include "../support.h"
18
 
#include <stdio.h>      //fopen
19
 
#include <glib.h>
20
 
#include <gtk/gtk.h>
21
 
#include <string.h>
22
 
 
23
 
#ifdef _WIN32
24
 
 #include <io.h>
25
 
 #ifndef __MINGW32__
26
 
  #define strcasecmp stricmp
27
 
 #endif
28
 
#endif
29
 
 
30
 
void replaceall(std::string &strData, const char *szFind, const char *szReplace);
31
 
int gtkMessageBox(const char *szText, int nButtons = GTK_BUTTONS_OK, int nIcon = GTK_MESSAGE_INFO);
32
 
 
33
 
FormatIO_MMLX::FormatIO_MMLX()
34
 
{
35
 
        m_nCurParentID = -1;    //TOFIX use Idx for faster operation
36
 
        m_nCurNodeID = -1;
37
 
        m_nLastNodeLevel = -1;
38
 
        m_nCurTextLine = 0;
39
 
        m_nCoversionFailuresCnt = 0;
40
 
}
41
 
 
42
 
FormatIO_MMLX::~FormatIO_MMLX()
43
 
{
44
 
}
45
 
 
46
 
int FormatIO_MMLX::Load(const char *szFile, NoteDocument &doc)
47
 
{
48
 
        m_pDoc = &doc;  //store pointer
49
 
 
50
 
        //clear old document contents
51
 
        doc.Clear();
52
 
 
53
 
        FILE *pInFile = fopen(szFile, "r");
54
 
        if(NULL == pInFile)
55
 
                return DOC_LOAD_NOT_FOUND;
56
 
 
57
 
        m_nCurTextLine = 0;
58
 
 
59
 
        char szBuffer[1024];
60
 
 
61
 
        //TOFIX error handling
62
 
        while(NULL != fgets(szBuffer, sizeof(szBuffer), pInFile))
63
 
        {
64
 
                RunLoop();      //enable progress painting events
65
 
 
66
 
                //kill new line char(s)
67
 
                if('\n'== szBuffer[strlen(szBuffer)-1])
68
 
                        szBuffer[strlen(szBuffer)-1] = '\0';
69
 
                if('\r'== szBuffer[strlen(szBuffer)-1])
70
 
                        szBuffer[strlen(szBuffer)-1] = '\0';
71
 
 
72
 
                m_nCurTextLine ++;
73
 
                ParseLine(szBuffer);
74
 
        }
75
 
        fclose(pInFile);
76
 
 
77
 
#ifdef _ZAURUS_BUILD
78
 
        if(m_nCoversionFailuresCnt > 0)
79
 
                gtkMessageBox(_("There were problems converting text from ibm850 to utf-8.\nConsider installing \"glibc-gconv-ibm850\" package"));
80
 
#endif
81
 
 
82
 
        return DOC_LOAD_OK;
83
 
}
84
 
 
85
 
int FormatIO_MMLX::Save(const char *szFile, NoteDocument &doc)
86
 
{
87
 
        return DOC_SAVE_NOT_SUPPORTED;  //export not implemented
88
 
}
89
 
 
90
 
void FormatIO_MMLX::ParseLine(char *szBuffer)
91
 
{
92
 
        int nLen = (szBuffer) ? strlen(szBuffer) : 0;
93
 
 
94
 
        bool bIsText = false;
95
 
        if(0 == nLen || (nLen > 0 && szBuffer[0] != ' ')){
96
 
                bIsText = true;
97
 
        }
98
 
        //calculate depth of the new node (number of spaces before title)
99
 
        //NOTE: it might turn out that the text is not really a text ;)
100
 
        int nSpaces = 0;
101
 
        if(!bIsText){
102
 
                char *szPos = szBuffer;
103
 
                if(szPos){
104
 
                        while(*szPos==' '){
105
 
                                nSpaces ++; szPos ++;
106
 
                        }
107
 
                }
108
 
                if(nSpaces%3 != 0)
109
 
                        bIsText = true; // it is probably a text then
110
 
        }
111
 
 
112
 
        if(bIsText)
113
 
        {
114
 
                //append the text line to the current node
115
 
                int nIdx = m_pDoc->GetIdxFromID(m_nCurNodeID);
116
 
                if(nIdx >= 0)
117
 
                {
118
 
                        //parse out <NF1> tag (equals to empty line)
119
 
                        if(0 == strcmp("<NF1>", szBuffer)){
120
 
                                m_pDoc->GetNodeByIdx(nIdx).GetText() += "\n";
121
 
                                return;
122
 
                        }
123
 
                        //parse out <NF0> tag
124
 
                        if(0 == strcmp("<NF0>", szBuffer))
125
 
                                return;
126
 
 
127
 
                        //handle MM/LX subformat with text line indented and prefixed with '|'
128
 
                        const char *szPos = szBuffer;
129
 
                        if(szBuffer[0] == '|'){
130
 
                                szPos++;
131
 
                                int nMax = (m_nLastNodeLevel + 2) * 3 - 1;
132
 
                                for(int i=0; i<nMax; i++)
133
 
                                        if(*szPos == ' ')
134
 
                                                szPos++;
135
 
                                        else
136
 
                                                break;
137
 
                        }
138
 
 
139
 
                        //append text line to the current node
140
 
                        gchar *strUtf8 = g_convert(szPos, strlen (szPos), "UTF-8", "ibm850", NULL, NULL, NULL);
141
 
                        ASSERT(NULL != strUtf8);
142
 
                        if(NULL != strUtf8){
143
 
                                m_pDoc->GetNodeByIdx(nIdx).GetText() += strUtf8;
144
 
                                m_pDoc->GetNodeByIdx(nIdx).GetText() += "\n";
145
 
                                g_free(strUtf8);
146
 
                        }
147
 
                        else    //on error, fall back to unconverted text
148
 
                        {
149
 
                                m_nCoversionFailuresCnt ++;
150
 
                                m_pDoc->GetNodeByIdx(nIdx).GetText() += szPos;
151
 
                                m_pDoc->GetNodeByIdx(nIdx).GetText() += "\n";
152
 
                        }
153
 
                }
154
 
        }
155
 
        else{
156
 
                char *szPos = szBuffer + nSpaces;
157
 
 
158
 
                //calculate depth of the new node
159
 
                int nLevel = nSpaces/3 - 1; //starts from 0
160
 
 
161
 
                std::string strLinkUrl;
162
 
                bool bFinished = false;
163
 
 
164
 
                //check for link type 1  (link to another map file)
165
 
                char *szPosLink1 = strchr(szPos, 0x18);
166
 
                if(NULL != szPosLink1){
167
 
                        *szPosLink1 = '\0';
168
 
                        szPosLink1 ++;
169
 
 
170
 
                        //check if link points to some subnode within the map
171
 
                        char *szHash = strchr(szPosLink1, '#');
172
 
                        if(NULL != szHash)
173
 
                                *szHash = '\0'; //cut the hash part (currently not supported by notecase)
174
 
 
175
 
                        //extract link URL
176
 
                        gchar *strLinkUtf8 = g_convert(szPosLink1, strlen (szPosLink1), "UTF-8", "ibm850", NULL, NULL, NULL);
177
 
                        ASSERT(NULL != strLinkUtf8);
178
 
                        if(NULL != strLinkUtf8){
179
 
                                strLinkUrl = strLinkUtf8;
180
 
                                g_free(strLinkUtf8);
181
 
                        }
182
 
                        else{   //on error, fall back to unconverted text
183
 
                                m_nCoversionFailuresCnt ++;
184
 
                                strLinkUrl = szPosLink1;
185
 
                        }
186
 
                }
187
 
                else{
188
 
                        // check for link type 2 (link to ordinary file)
189
 
                        szPosLink1 = strchr(szPos, 0x19);
190
 
                        if(NULL != szPosLink1){
191
 
                                *szPosLink1 = '\0';
192
 
 
193
 
                                //extract link URL
194
 
                                szPosLink1 ++;
195
 
                                gchar *strLinkUtf8 = g_convert(szPosLink1, strlen (szPosLink1), "UTF-8", "ibm850", NULL, NULL, NULL);
196
 
                                ASSERT(NULL != strLinkUtf8);
197
 
                                if(NULL != strLinkUtf8){
198
 
                                        strLinkUrl = strLinkUtf8;
199
 
                                        g_free(strLinkUtf8);
200
 
                                }
201
 
                                else{   //on error, fall back to unconverted text
202
 
                                        m_nCoversionFailuresCnt ++;
203
 
                                        strLinkUrl = szPosLink1;
204
 
                                }
205
 
                        }
206
 
                }
207
 
 
208
 
                //check for finished char
209
 
                char *szPosFinished = strchr(szPos, 0xFB);
210
 
                if(NULL != szPosFinished){
211
 
                        *szPosFinished = '\0';
212
 
                        bFinished = true;
213
 
                }
214
 
 
215
 
        #ifdef _DEBUG
216
 
                if(strlen (szPos) == 0)
217
 
                        TRACE("ERROR: Invalid MM/LX file. Empty title detected!\n");
218
 
        #endif
219
 
 
220
 
                //convert text before using it
221
 
                gchar *strUtf8 = g_convert(szPos, strlen (szPos), "UTF-8", "ibm850", NULL, NULL, NULL);
222
 
                ASSERT(NULL != strUtf8);
223
 
 
224
 
        #ifdef _DEBUG
225
 
                if(!strUtf8)
226
 
                        TRACE("ERROR: Failed to convert from ibm850\n");
227
 
        #endif
228
 
 
229
 
                if(nLevel > m_nLastNodeLevel)
230
 
                {
231
 
                        //insert node as child of current node
232
 
                        m_pDoc->NodeInsert(m_nCurNodeID, -1);
233
 
                        m_nCurParentID = m_nCurNodeID;  //current node will become a new parent
234
 
                        m_nCurNodeID   = m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).m_nID;
235
 
                }
236
 
                else if(nLevel == m_nLastNodeLevel)
237
 
                {
238
 
                        //insert node as sibling of current node
239
 
                        m_pDoc->NodeInsert(m_nCurParentID, -1);
240
 
                        m_nCurNodeID   = m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).m_nID;
241
 
                }
242
 
                else{
243
 
                        DocumentIterator it(*m_pDoc);
244
 
 
245
 
                        //step back X levels and create child there
246
 
                        int nDiff = m_nLastNodeLevel - nLevel;
247
 
                        while(nDiff > 0 && m_nCurParentID >= 0){
248
 
                                m_nCurParentID = it.GetNodeByID(m_nCurParentID).m_nParentID;
249
 
                                nDiff --;
250
 
                        }
251
 
 
252
 
                        m_pDoc->NodeInsert(m_nCurParentID, -1);
253
 
                        m_nCurNodeID   = m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).m_nID;
254
 
                }
255
 
 
256
 
                //set link
257
 
                if(strLinkUrl.size() > 0){
258
 
                        m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).m_objLink.m_strTargetURL = strLinkUrl;
259
 
                }
260
 
 
261
 
                //set finished
262
 
                if(bFinished)
263
 
                        m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).m_bFinished = true;
264
 
 
265
 
                //set title
266
 
                bool bFree = true;
267
 
                if(NULL == strUtf8){    //on error, fall back to unconverted text
268
 
                        m_nCoversionFailuresCnt ++;
269
 
                        strUtf8 = szPos;
270
 
                        bFree = false;
271
 
                }
272
 
                if(NULL != strUtf8){
273
 
                        std::string strTitle(strUtf8);
274
 
 
275
 
                        //remove hotkey (&) cahracter if found
276
 
                        replaceall(strTitle, "&", "");
277
 
 
278
 
                        //recognize if the title is an icon
279
 
                        if(strTitle.size() > 4){
280
 
                                if(0 == strcasecmp(strTitle.substr(strTitle.size()-4).c_str(), ".icn")){
281
 
                                        strTitle.insert(0, "[ICON: ");
282
 
                                        strTitle += "]";
283
 
                                }
284
 
                        }
285
 
 
286
 
                        m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).SetTitle(strTitle.c_str());
287
 
                        if(bFree)
288
 
                                g_free(strUtf8);
289
 
                }
290
 
 
291
 
                m_nLastNodeLevel = nLevel;
292
 
        }
293
 
}
 
1
////////////////////////////////////////////////////////////////////////////
 
2
// NoteCase notes manager project <http://notecase.sf.net>
 
3
//
 
4
// This code is licensed under BSD license.See "license.txt" for more details.
 
5
//
 
6
// File: Implements MM/LX Mindmap/Outline document format I/O (reading only)
 
7
////////////////////////////////////////////////////////////////////////////
 
8
 
 
9
#if _MSC_VER > 1000
 
10
  #pragma warning(disable: 4996)        //ignore deprecated functions warning
 
11
#endif
 
12
 
 
13
#include "FormatIOMMLX.h"
 
14
#include "DocumentIterator.h"
 
15
#include "debug.h"
 
16
#include "../config.h"
 
17
#include "../support.h"
 
18
#include <stdio.h>      //fopen
 
19
#include <glib.h>
 
20
#include <gtk/gtk.h>
 
21
#include <string.h>
 
22
 
 
23
#ifdef _WIN32
 
24
 #include <io.h>
 
25
 #ifndef __MINGW32__
 
26
  #define strcasecmp stricmp
 
27
 #endif
 
28
#endif
 
29
 
 
30
void replaceall(std::string &strData, const char *szFind, const char *szReplace);
 
31
int gtkMessageBox(const char *szText, int nButtons = GTK_BUTTONS_OK, int nIcon = GTK_MESSAGE_INFO);
 
32
 
 
33
FormatIO_MMLX::FormatIO_MMLX()
 
34
{
 
35
        m_nCurParentID = -1;    //TOFIX use Idx for faster operation
 
36
        m_nCurNodeID = -1;
 
37
        m_nLastNodeLevel = -1;
 
38
        m_nCurTextLine = 0;
 
39
        m_nCoversionFailuresCnt = 0;
 
40
}
 
41
 
 
42
FormatIO_MMLX::~FormatIO_MMLX()
 
43
{
 
44
}
 
45
 
 
46
int FormatIO_MMLX::Load(const char *szFile, NoteDocument &doc)
 
47
{
 
48
        m_pDoc = &doc;  //store pointer
 
49
 
 
50
        //clear old document contents
 
51
        doc.Clear();
 
52
 
 
53
        FILE *pInFile = fopen(szFile, "r");
 
54
        if(NULL == pInFile)
 
55
                return DOC_LOAD_NOT_FOUND;
 
56
 
 
57
        m_nCurTextLine = 0;
 
58
 
 
59
        char szBuffer[1024];
 
60
 
 
61
        //TOFIX error handling
 
62
        while(NULL != fgets(szBuffer, sizeof(szBuffer), pInFile))
 
63
        {
 
64
                RunLoop();      //enable progress painting events
 
65
 
 
66
                //kill new line char(s)
 
67
                if('\n'== szBuffer[strlen(szBuffer)-1])
 
68
                        szBuffer[strlen(szBuffer)-1] = '\0';
 
69
                if('\r'== szBuffer[strlen(szBuffer)-1])
 
70
                        szBuffer[strlen(szBuffer)-1] = '\0';
 
71
 
 
72
                m_nCurTextLine ++;
 
73
                ParseLine(szBuffer);
 
74
        }
 
75
        fclose(pInFile);
 
76
 
 
77
#ifdef _ZAURUS_BUILD
 
78
        if(m_nCoversionFailuresCnt > 0)
 
79
                gtkMessageBox(_("There were problems converting text from ibm850 to utf-8.\nConsider installing \"glibc-gconv-ibm850\" package"));
 
80
#endif
 
81
 
 
82
        return DOC_LOAD_OK;
 
83
}
 
84
 
 
85
int FormatIO_MMLX::Save(const char *szFile, NoteDocument &doc)
 
86
{
 
87
        return DOC_SAVE_NOT_SUPPORTED;  //export not implemented
 
88
}
 
89
 
 
90
void FormatIO_MMLX::ParseLine(char *szBuffer)
 
91
{
 
92
        int nLen = (szBuffer) ? strlen(szBuffer) : 0;
 
93
 
 
94
        bool bIsText = false;
 
95
        if(0 == nLen || (nLen > 0 && szBuffer[0] != ' ')){
 
96
                bIsText = true;
 
97
        }
 
98
        //calculate depth of the new node (number of spaces before title)
 
99
        //NOTE: it might turn out that the text is not really a text ;)
 
100
        int nSpaces = 0;
 
101
        if(!bIsText){
 
102
                char *szPos = szBuffer;
 
103
                if(szPos){
 
104
                        while(*szPos==' '){
 
105
                                nSpaces ++; szPos ++;
 
106
                        }
 
107
                }
 
108
                if(nSpaces%3 != 0)
 
109
                        bIsText = true; // it is probably a text then
 
110
        }
 
111
 
 
112
        if(bIsText)
 
113
        {
 
114
                //append the text line to the current node
 
115
                int nIdx = m_pDoc->GetIdxFromID(m_nCurNodeID);
 
116
                if(nIdx >= 0)
 
117
                {
 
118
                        //parse out <NF1> tag (equals to empty line)
 
119
                        if(0 == strcmp("<NF1>", szBuffer)){
 
120
                                m_pDoc->GetNodeByIdx(nIdx).GetText() += "\n";
 
121
                                return;
 
122
                        }
 
123
                        //parse out <NF0> tag
 
124
                        if(0 == strcmp("<NF0>", szBuffer))
 
125
                                return;
 
126
 
 
127
                        //handle MM/LX subformat with text line indented and prefixed with '|'
 
128
                        const char *szPos = szBuffer;
 
129
                        if(szBuffer[0] == '|'){
 
130
                                szPos++;
 
131
                                int nMax = (m_nLastNodeLevel + 2) * 3 - 1;
 
132
                                for(int i=0; i<nMax; i++)
 
133
                                        if(*szPos == ' ')
 
134
                                                szPos++;
 
135
                                        else
 
136
                                                break;
 
137
                        }
 
138
 
 
139
                        //append text line to the current node
 
140
                        gchar *strUtf8 = g_convert(szPos, strlen (szPos), "UTF-8", "ibm850", NULL, NULL, NULL);
 
141
                        ASSERT(NULL != strUtf8);
 
142
                        if(NULL != strUtf8){
 
143
                                m_pDoc->GetNodeByIdx(nIdx).GetText() += strUtf8;
 
144
                                m_pDoc->GetNodeByIdx(nIdx).GetText() += "\n";
 
145
                                g_free(strUtf8);
 
146
                        }
 
147
                        else    //on error, fall back to unconverted text
 
148
                        {
 
149
                                m_nCoversionFailuresCnt ++;
 
150
                                m_pDoc->GetNodeByIdx(nIdx).GetText() += szPos;
 
151
                                m_pDoc->GetNodeByIdx(nIdx).GetText() += "\n";
 
152
                        }
 
153
                }
 
154
        }
 
155
        else{
 
156
                char *szPos = szBuffer + nSpaces;
 
157
 
 
158
                //calculate depth of the new node
 
159
                int nLevel = nSpaces/3 - 1; //starts from 0
 
160
 
 
161
                std::string strLinkUrl;
 
162
                bool bFinished = false;
 
163
 
 
164
                //check for link type 1  (link to another map file)
 
165
                char *szPosLink1 = strchr(szPos, 0x18);
 
166
                if(NULL != szPosLink1){
 
167
                        *szPosLink1 = '\0';
 
168
                        szPosLink1 ++;
 
169
 
 
170
                        //check if link points to some subnode within the map
 
171
                        char *szHash = strchr(szPosLink1, '#');
 
172
                        if(NULL != szHash)
 
173
                                *szHash = '\0'; //cut the hash part (currently not supported by notecase)
 
174
 
 
175
                        //extract link URL
 
176
                        gchar *strLinkUtf8 = g_convert(szPosLink1, strlen (szPosLink1), "UTF-8", "ibm850", NULL, NULL, NULL);
 
177
                        ASSERT(NULL != strLinkUtf8);
 
178
                        if(NULL != strLinkUtf8){
 
179
                                strLinkUrl = strLinkUtf8;
 
180
                                g_free(strLinkUtf8);
 
181
                        }
 
182
                        else{   //on error, fall back to unconverted text
 
183
                                m_nCoversionFailuresCnt ++;
 
184
                                strLinkUrl = szPosLink1;
 
185
                        }
 
186
                }
 
187
                else{
 
188
                        // check for link type 2 (link to ordinary file)
 
189
                        szPosLink1 = strchr(szPos, 0x19);
 
190
                        if(NULL != szPosLink1){
 
191
                                *szPosLink1 = '\0';
 
192
 
 
193
                                //extract link URL
 
194
                                szPosLink1 ++;
 
195
                                gchar *strLinkUtf8 = g_convert(szPosLink1, strlen (szPosLink1), "UTF-8", "ibm850", NULL, NULL, NULL);
 
196
                                ASSERT(NULL != strLinkUtf8);
 
197
                                if(NULL != strLinkUtf8){
 
198
                                        strLinkUrl = strLinkUtf8;
 
199
                                        g_free(strLinkUtf8);
 
200
                                }
 
201
                                else{   //on error, fall back to unconverted text
 
202
                                        m_nCoversionFailuresCnt ++;
 
203
                                        strLinkUrl = szPosLink1;
 
204
                                }
 
205
                        }
 
206
                }
 
207
 
 
208
                //check for finished char
 
209
                char *szPosFinished = strchr(szPos, 0xFB);
 
210
                if(NULL != szPosFinished){
 
211
                        *szPosFinished = '\0';
 
212
                        bFinished = true;
 
213
                }
 
214
 
 
215
        #ifdef _DEBUG
 
216
                if(strlen (szPos) == 0)
 
217
                        TRACE("ERROR: Invalid MM/LX file. Empty title detected!\n");
 
218
        #endif
 
219
 
 
220
                //convert text before using it
 
221
                gchar *strUtf8 = g_convert(szPos, strlen (szPos), "UTF-8", "ibm850", NULL, NULL, NULL);
 
222
                ASSERT(NULL != strUtf8);
 
223
 
 
224
        #ifdef _DEBUG
 
225
                if(!strUtf8)
 
226
                        TRACE("ERROR: Failed to convert from ibm850\n");
 
227
        #endif
 
228
 
 
229
                if(nLevel > m_nLastNodeLevel)
 
230
                {
 
231
                        //insert node as child of current node
 
232
                        m_pDoc->NodeInsert(m_nCurNodeID, -1);
 
233
                        m_nCurParentID = m_nCurNodeID;  //current node will become a new parent
 
234
                        m_nCurNodeID   = m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).m_nID;
 
235
                }
 
236
                else if(nLevel == m_nLastNodeLevel)
 
237
                {
 
238
                        //insert node as sibling of current node
 
239
                        m_pDoc->NodeInsert(m_nCurParentID, -1);
 
240
                        m_nCurNodeID   = m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).m_nID;
 
241
                }
 
242
                else{
 
243
                        DocumentIterator it(*m_pDoc);
 
244
 
 
245
                        //step back X levels and create child there
 
246
                        int nDiff = m_nLastNodeLevel - nLevel;
 
247
                        while(nDiff > 0 && m_nCurParentID >= 0){
 
248
                                m_nCurParentID = it.GetNodeByID(m_nCurParentID).m_nParentID;
 
249
                                nDiff --;
 
250
                        }
 
251
 
 
252
                        m_pDoc->NodeInsert(m_nCurParentID, -1);
 
253
                        m_nCurNodeID   = m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).m_nID;
 
254
                }
 
255
 
 
256
                //set link
 
257
                if(strLinkUrl.size() > 0){
 
258
                        m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).m_objLink.m_strTargetURL = strLinkUrl;
 
259
                }
 
260
 
 
261
                //set finished
 
262
                if(bFinished)
 
263
                        m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).m_bFinished = true;
 
264
 
 
265
                //set title
 
266
                bool bFree = true;
 
267
                if(NULL == strUtf8){    //on error, fall back to unconverted text
 
268
                        m_nCoversionFailuresCnt ++;
 
269
                        strUtf8 = szPos;
 
270
                        bFree = false;
 
271
                }
 
272
                if(NULL != strUtf8){
 
273
                        std::string strTitle(strUtf8);
 
274
 
 
275
                        //remove hotkey (&) cahracter if found
 
276
                        replaceall(strTitle, "&", "");
 
277
 
 
278
                        //recognize if the title is an icon
 
279
                        if(strTitle.size() > 4){
 
280
                                if(0 == strcasecmp(strTitle.substr(strTitle.size()-4).c_str(), ".icn")){
 
281
                                        strTitle.insert(0, "[ICON: ");
 
282
                                        strTitle += "]";
 
283
                                }
 
284
                        }
 
285
 
 
286
                        m_pDoc->GetNodeByIdx(m_pDoc->GetNodeCount()-1).SetTitle(strTitle.c_str());
 
287
                        if(bFree)
 
288
                                g_free(strUtf8);
 
289
                }
 
290
 
 
291
                m_nLastNodeLevel = nLevel;
 
292
        }
 
293
}