Diffstat (limited to 'core/apps/embeddedkonsole/TEHistory.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | core/apps/embeddedkonsole/TEHistory.cpp | 275 |
1 files changed, 143 insertions, 132 deletions
diff --git a/core/apps/embeddedkonsole/TEHistory.cpp b/core/apps/embeddedkonsole/TEHistory.cpp index db9d10c..504cd13 100644 --- a/core/apps/embeddedkonsole/TEHistory.cpp +++ b/core/apps/embeddedkonsole/TEHistory.cpp | |||
@@ -7,9 +7,9 @@ | |||
7 | /* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */ | 7 | /* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */ |
8 | /* */ | 8 | /* */ |
9 | /* This file is part of Konsole - an X terminal for KDE */ | 9 | /* This file is part of Qkonsole - an X terminal for KDE */ |
10 | /* */ | 10 | /* */ |
11 | /* -------------------------------------------------------------------------- */ | 11 | /* -------------------------------------------------------------------------- */ |
12 | /* */ | 12 | /* */ |
13 | /* Ported Konsole to Qt/Embedded */ | 13 | /* Ported Qkonsole to Qt/Embedded */ |
14 | /* */ | 14 | /* */ |
15 | /* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */ | 15 | /* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */ |
@@ -25,4 +25,6 @@ | |||
25 | #include <errno.h> | 25 | #include <errno.h> |
26 | 26 | ||
27 | #include <qpe/config.h> | ||
28 | |||
27 | #define HERE printf("%s(%d): here\n",__FILE__,__LINE__) | 29 | #define HERE printf("%s(%d): here\n",__FILE__,__LINE__) |
28 | 30 | ||
@@ -41,142 +43,73 @@ | |||
41 | at constant costs. | 43 | at constant costs. |
42 | 44 | ||
43 | FIXME: some complain about the history buffer comsuming the | ||
44 | memory of their machines. This problem is critical | ||
45 | since the history does not behave gracefully in cases | ||
46 | where the memory is used up completely. | ||
47 | |||
48 | I put in a workaround that should handle it problem | ||
49 | now gracefully. I'm not satisfied with the solution. | ||
50 | |||
51 | FIXME: Terminating the history is not properly indicated | ||
52 | in the menu. We should throw a signal. | ||
53 | |||
54 | FIXME: There is noticable decrease in speed, also. Perhaps, | ||
55 | there whole feature needs to be revisited therefore. | ||
56 | Disadvantage of a more elaborated, say block-oriented | ||
57 | scheme with wrap around would be it's complexity. | ||
58 | */ | 45 | */ |
59 | 46 | ||
60 | //FIXME: tempory replacement for tmpfile | ||
61 | // this is here one for debugging purpose. | ||
62 | |||
63 | //#define tmpfile xTmpFile | ||
64 | |||
65 | FILE* xTmpFile() | ||
66 | { | ||
67 | static int fid = 0; | ||
68 | char fname[80]; | ||
69 | sprintf(fname,"TmpFile.%d",fid++); | ||
70 | return fopen(fname,"w"); | ||
71 | } | ||
72 | |||
73 | 47 | ||
74 | // History Buffer /////////////////////////////////////////// | 48 | HistoryScroll::HistoryScroll() |
75 | |||
76 | /* | ||
77 | A Row(X) data type which allows adding elements to the end. | ||
78 | */ | ||
79 | |||
80 | HistoryBuffer::HistoryBuffer() | ||
81 | { | 49 | { |
82 | ion = -1; | 50 | m_lines = NULL; |
83 | length = 0; | 51 | m_max_lines = 0; |
52 | m_cells = NULL; | ||
53 | m_max_cells = 0; | ||
54 | m_num_lines = 0; | ||
55 | m_first_line = 0; | ||
56 | m_last_cell = 0; | ||
57 | m_start_line = 0; | ||
84 | } | 58 | } |
85 | 59 | ||
86 | HistoryBuffer::~HistoryBuffer() | 60 | HistoryScroll::~HistoryScroll() |
87 | { | 61 | { |
88 | setScroll(FALSE); | 62 | setSize(0,0); |
89 | } | 63 | } |
90 | 64 | ||
91 | void HistoryBuffer::setScroll(bool on) | 65 | void HistoryScroll::setSize(int lines, int cells) |
92 | { | 66 | { |
93 | if (on == hasScroll()) return; | 67 | // could try to preserve the existing data... |
94 | 68 | // printf("setSize(%d,%d)\n", lines, cells); | |
95 | if (on) | 69 | if (m_lines) { |
96 | { | 70 | delete m_lines; |
97 | assert( ion < 0 ); | 71 | m_lines = NULL; |
98 | assert( length == 0); | ||
99 | FILE* tmp = tmpfile(); if (!tmp) { perror("konsole: cannot open temp file.\n"); return; } | ||
100 | ion = dup(fileno(tmp)); if (ion<0) perror("konsole: cannot dup temp file.\n"); | ||
101 | fclose(tmp); | ||
102 | } | 72 | } |
103 | else | 73 | if (m_cells) { |
104 | { | 74 | delete m_cells; |
105 | assert( ion >= 0 ); | 75 | m_cells = NULL; |
106 | close(ion); | ||
107 | ion = -1; | ||
108 | length = 0; | ||
109 | } | 76 | } |
77 | m_max_lines = m_max_cells = 0; | ||
78 | if (lines > 0 && cells > 0) { | ||
79 | m_max_lines = lines; | ||
80 | m_lines = new int[m_max_lines]; | ||
81 | m_lines[0] = 0; | ||
82 | m_max_cells = cells; | ||
83 | m_cells = new ca[m_max_cells]; | ||
84 | } | ||
85 | m_first_line = 0; | ||
86 | m_num_lines = 0; | ||
87 | m_last_cell = 0; | ||
88 | m_start_line = 0; | ||
110 | } | 89 | } |
111 | 90 | ||
112 | bool HistoryBuffer::hasScroll() | ||
113 | { | ||
114 | return ion >= 0; | ||
115 | } | ||
116 | |||
117 | void HistoryBuffer::add(const unsigned char* bytes, int len) | ||
118 | { int rc; | ||
119 | assert(hasScroll()); | ||
120 | rc = lseek( ion, length, SEEK_SET); | ||
121 | if (rc < 0) { perror("HistoryBuffer::add.seek"); setScroll(FALSE); return; } | ||
122 | rc = write( ion, bytes, len); | ||
123 | if (rc < 0) { perror("HistoryBuffer::add.write"); setScroll(FALSE); return; } | ||
124 | length += rc; | ||
125 | } | ||
126 | |||
127 | void HistoryBuffer::get(unsigned char* bytes, int len, int loc) { | ||
128 | int rc; | ||
129 | assert(hasScroll()); | ||
130 | // qDebug("history get len %d, loc %d, length %d", len, loc, length); | ||
131 | if (loc < 0 || len < 0 || loc + len > length) | ||
132 | fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc); | ||
133 | |||
134 | rc = lseek( ion, loc, SEEK_SET); | ||
135 | if (rc < 0) { perror("HistoryBuffer::get.seek"); setScroll(FALSE); return; } | ||
136 | rc = read( ion, bytes, len); | ||
137 | if (rc < 0) { perror("HistoryBuffer::get.read"); setScroll(FALSE); return; } | ||
138 | } | ||
139 | |||
140 | int HistoryBuffer::len() | ||
141 | { | ||
142 | return length; | ||
143 | } | ||
144 | |||
145 | // History Scroll ////////////////////////////////////// | ||
146 | |||
147 | /* | ||
148 | The history scroll makes a Row(Row(Cell)) from | ||
149 | two history buffers. The index buffer contains | ||
150 | start of line positions which refere to the cells | ||
151 | buffer. | ||
152 | |||
153 | Note that index[0] addresses the second line | ||
154 | (line #1), while the first line (line #0) starts | ||
155 | at 0 in cells. | ||
156 | */ | ||
157 | |||
158 | HistoryScroll::HistoryScroll() | ||
159 | { | ||
160 | } | ||
161 | |||
162 | HistoryScroll::~HistoryScroll() | ||
163 | { | ||
164 | } | ||
165 | |||
166 | void HistoryScroll::setScroll(bool on) | 91 | void HistoryScroll::setScroll(bool on) |
167 | { | 92 | { |
168 | index.setScroll(on); | 93 | Config cfg("Qkonsole"); |
169 | cells.setScroll(on); | 94 | cfg.setGroup("History"); |
95 | // printf("setScroll(%d)\n", on); | ||
96 | if (on) { | ||
97 | int lines = cfg.readNumEntry("history_lines",300); | ||
98 | int avg_line = cfg.readNumEntry("avg_line_length",60); | ||
99 | int cells = lines * avg_line; | ||
100 | setSize(lines,cells); | ||
101 | } else { | ||
102 | setSize(0,0); | ||
103 | } | ||
170 | } | 104 | } |
171 | 105 | ||
172 | bool HistoryScroll::hasScroll() | 106 | bool HistoryScroll::hasScroll() |
173 | { | 107 | { |
174 | return index.hasScroll() && cells.hasScroll(); | 108 | return (m_max_lines > 0); |
175 | } | 109 | } |
176 | 110 | ||
177 | int HistoryScroll::getLines() | 111 | int HistoryScroll::getLines() |
178 | { | 112 | { |
179 | if (!hasScroll()) return 0; | 113 | return(m_num_lines); |
180 | return index.len() / sizeof(int); | ||
181 | } | 114 | } |
182 | 115 | ||
@@ -184,30 +117,95 @@ int HistoryScroll::getLineLen(int lineno) | |||
184 | { | 117 | { |
185 | if (!hasScroll()) return 0; | 118 | if (!hasScroll()) return 0; |
186 | return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(ca); | 119 | if (lineno >= m_num_lines) { |
120 | // printf("getLineLen(%d) out of range %d\n", lineno, m_num_lines); | ||
121 | return(0); | ||
122 | } | ||
123 | int len = startOfLine(lineno+1) - startOfLine(lineno); | ||
124 | if (len < 0) { | ||
125 | len += m_max_cells; | ||
126 | } | ||
127 | // printf("getLineLen(%d) = %d\n", lineno, len); | ||
128 | return(len); | ||
187 | } | 129 | } |
188 | 130 | ||
189 | int HistoryScroll::startOfLine(int lineno) | 131 | int HistoryScroll::startOfLine(int lineno) |
190 | { | 132 | { |
191 | if (lineno <= 0) return 0; | 133 | // printf("startOfLine(%d) =", lineno); |
192 | if (!hasScroll()) return 0; | 134 | if (!hasScroll()) return 0; |
193 | if (lineno <= getLines()) | 135 | assert(lineno >= 0 && lineno <= m_num_lines); |
194 | { int res; | 136 | if (lineno < m_num_lines) { |
195 | index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int)); | 137 | int index = lineno + m_first_line; |
196 | return res; | 138 | if (index >= m_max_lines) |
139 | index -= m_max_lines; | ||
140 | // printf("%d\n", m_lines[index]); | ||
141 | return(m_lines[index]); | ||
142 | } else { | ||
143 | // printf("last %d\n", m_last_cell); | ||
144 | return(m_last_cell); | ||
197 | } | 145 | } |
198 | return cells.len(); | ||
199 | } | 146 | } |
200 | 147 | ||
201 | void HistoryScroll::getCells(int lineno, int colno, int count, ca res[]) | 148 | void HistoryScroll::getCells(int lineno, int colno, int count, ca *res) |
202 | { | 149 | { |
150 | // printf("getCells(%d,%d,%d) num_lines=%d\n", lineno, colno, count, m_num_lines); | ||
203 | assert(hasScroll()); | 151 | assert(hasScroll()); |
204 | //get(unsigned char* bytes, int len, int loc) | 152 | assert(lineno >= 0 && lineno < m_num_lines); |
205 | cells.get( (unsigned char*)res, count * sizeof(ca), startOfLine( lineno) + colno * sizeof(ca) ); | 153 | int index = lineno + m_first_line; |
154 | if (index >= m_max_lines) | ||
155 | index -= m_max_lines; | ||
156 | assert(index >= 0 && index < m_max_lines); | ||
157 | index = m_lines[index] + colno; | ||
158 | assert(index >= 0 && index < m_max_cells); | ||
159 | while(count-- > 0) { | ||
160 | *res++ = m_cells[index]; | ||
161 | if (++index >= m_max_cells) { | ||
162 | index = 0; | ||
163 | } | ||
164 | } | ||
206 | } | 165 | } |
207 | 166 | ||
208 | void HistoryScroll::addCells(ca text[], int count) | 167 | void HistoryScroll::addCells(ca *text, int count) |
209 | { | 168 | { |
210 | if (!hasScroll()) return; | 169 | if (!hasScroll()) return; |
211 | cells.add((unsigned char*)text,count*sizeof(ca)); | 170 | int start_cell = m_last_cell; |
171 | // printf("addCells count=%d start=%d first_line=%d first_cell=%d lines=%d\n", | ||
172 | // count, start_cell, m_first_line, m_lines[m_first_line], m_num_lines); | ||
173 | if (count <= 0) { | ||
174 | return; | ||
175 | } | ||
176 | while(count-- > 0) { | ||
177 | assert (m_last_cell >= 0 && m_last_cell < m_max_cells ); | ||
178 | m_cells[m_last_cell] = *text++; | ||
179 | if (++m_last_cell >= m_max_cells) { | ||
180 | m_last_cell = 0; | ||
181 | } | ||
182 | } | ||
183 | if (m_num_lines > 1) { | ||
184 | if (m_last_cell > start_cell) { | ||
185 | while(m_num_lines > 0 | ||
186 | && m_lines[m_first_line] >= start_cell | ||
187 | && m_lines[m_first_line] < m_last_cell) { | ||
188 | // printf("A remove %d>%d && %d<%d first_line=%d num_lines=%d\n", | ||
189 | // m_lines[m_first_line], start_cell, m_lines[m_first_line], m_last_cell, | ||
190 | // m_first_line, m_num_lines); | ||
191 | if (++m_first_line >= m_max_lines) { | ||
192 | m_first_line = 0; | ||
193 | } | ||
194 | m_num_lines--; | ||
195 | } | ||
196 | } else { | ||
197 | while(m_num_lines > 0 | ||
198 | && (m_lines[m_first_line] >= start_cell | ||
199 | || m_lines[m_first_line] < m_last_cell)) { | ||
200 | // printf("B remove %d>%d || %d<%d first_line=%d num_lines=%d\n", | ||
201 | // m_lines[m_first_line], start_cell, m_lines[m_first_line], m_last_cell, | ||
202 | // m_first_line, m_num_lines); | ||
203 | if (++m_first_line >= m_max_lines) { | ||
204 | m_first_line = 0; | ||
205 | } | ||
206 | m_num_lines--; | ||
207 | } | ||
208 | } | ||
209 | } | ||
212 | } | 210 | } |
213 | 211 | ||
@@ -215,5 +213,18 @@ void HistoryScroll::addLine() | |||
215 | { | 213 | { |
216 | if (!hasScroll()) return; | 214 | if (!hasScroll()) return; |
217 | int locn = cells.len(); | 215 | int index = m_first_line + m_num_lines; |
218 | index.add((unsigned char*)&locn,sizeof(int)); | 216 | if (index >= m_max_lines) { |
217 | index -= m_max_lines; | ||
218 | } | ||
219 | // printf("addLine line=%d cell=%d\n", index, m_last_cell); | ||
220 | assert(index >= 0 && index < m_max_lines); | ||
221 | m_lines[index] = m_start_line; | ||
222 | m_start_line = m_last_cell; | ||
223 | if (m_num_lines >= m_max_lines) { | ||
224 | if (++m_first_line >= m_num_lines) { | ||
225 | m_first_line = 0; | ||
226 | } | ||
227 | } else { | ||
228 | m_num_lines++; | ||
229 | } | ||
219 | } | 230 | } |