Diffstat (limited to 'noncore/apps/opie-console/history.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | noncore/apps/opie-console/history.cpp | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/noncore/apps/opie-console/history.cpp b/noncore/apps/opie-console/history.cpp new file mode 100644 index 0000000..3b82d16 --- a/dev/null +++ b/noncore/apps/opie-console/history.cpp | |||
@@ -0,0 +1,218 @@ | |||
1 | /* -------------------------------------------------------------------------- */ | ||
2 | /* */ | ||
3 | /* [history.c] History Buffer */ | ||
4 | /* */ | ||
5 | /* -------------------------------------------------------------------------- */ | ||
6 | /* */ | ||
7 | /* Copyright (c) 1997,1998 by Lars Doelle <lars.doelle@on-line.de> */ | ||
8 | /* */ | ||
9 | /* This file is part of Konsole - an X terminal for KDE */ | ||
10 | /* */ | ||
11 | /* -------------------------------------------------------------------------- */ | ||
12 | /* */ | ||
13 | /* Ported Konsole to Qt/Embedded */ | ||
14 | /* */ | ||
15 | /* Copyright (C) 2000 by John Ryland <jryland@trolltech.com> */ | ||
16 | /* */ | ||
17 | /* -------------------------------------------------------------------------- */ | ||
18 | /* */ | ||
19 | /* Ported embedded-Konsole to opie-console */ | ||
20 | /* */ | ||
21 | /* Copyright (C) 2002 by opie developers <opie@handhelds.org> */ | ||
22 | /* */ | ||
23 | /* -------------------------------------------------------------------------- */ | ||
24 | |||
25 | #include "history.h" | ||
26 | #include <stdlib.h> | ||
27 | #include <assert.h> | ||
28 | #include <stdio.h> | ||
29 | #include <sys/types.h> | ||
30 | #include <unistd.h> | ||
31 | #include <errno.h> | ||
32 | |||
33 | #define HERE printf("%s(%d): here\n",__FILE__,__LINE__) | ||
34 | |||
35 | /* | ||
36 | An arbitrary long scroll. | ||
37 | |||
38 | One can modify the scroll only by adding either cells | ||
39 | or newlines, but access it randomly. | ||
40 | |||
41 | The model is that of an arbitrary wide typewriter scroll | ||
42 | in that the scroll is a serie of lines and each line is | ||
43 | a serie of cells with no overwriting permitted. | ||
44 | |||
45 | The implementation provides arbitrary length and numbers | ||
46 | of cells and line/column indexed read access to the scroll | ||
47 | at constant costs. | ||
48 | |||
49 | FIXME: some complain about the history buffer comsuming the | ||
50 | memory of their machines. This problem is critical | ||
51 | since the history does not behave gracefully in cases | ||
52 | where the memory is used up completely. | ||
53 | |||
54 | I put in a workaround that should handle it problem | ||
55 | now gracefully. I'm not satisfied with the solution. | ||
56 | |||
57 | FIXME: Terminating the history is not properly indicated | ||
58 | in the menu. We should throw a signal. | ||
59 | |||
60 | FIXME: There is noticable decrease in speed, also. Perhaps, | ||
61 | there whole feature needs to be revisited therefore. | ||
62 | Disadvantage of a more elaborated, say block-oriented | ||
63 | scheme with wrap around would be it's complexity. | ||
64 | */ | ||
65 | |||
66 | //FIXME: tempory replacement for tmpfile | ||
67 | // this is here one for debugging purpose. | ||
68 | |||
69 | //#define tmpfile xTmpFile | ||
70 | |||
71 | FILE* xTmpFile() | ||
72 | { | ||
73 | static int fid = 0; | ||
74 | char fname[80]; | ||
75 | sprintf(fname,"TmpFile.%d",fid++); | ||
76 | return fopen(fname,"w"); | ||
77 | } | ||
78 | |||
79 | |||
80 | // History Buffer /////////////////////////////////////////// | ||
81 | |||
82 | /* | ||
83 | A Row(X) data type which allows adding elements to the end. | ||
84 | */ | ||
85 | |||
86 | HistoryBuffer::HistoryBuffer() | ||
87 | { | ||
88 | ion = -1; | ||
89 | length = 0; | ||
90 | } | ||
91 | |||
92 | HistoryBuffer::~HistoryBuffer() | ||
93 | { | ||
94 | setScroll(FALSE); | ||
95 | } | ||
96 | |||
97 | void HistoryBuffer::setScroll(bool on) | ||
98 | { | ||
99 | if (on == hasScroll()) return; | ||
100 | |||
101 | if (on) | ||
102 | { | ||
103 | assert( ion < 0 ); | ||
104 | assert( length == 0); | ||
105 | FILE* tmp = tmpfile(); if (!tmp) { perror("konsole: cannot open temp file.\n"); return; } | ||
106 | ion = dup(fileno(tmp)); if (ion<0) perror("konsole: cannot dup temp file.\n"); | ||
107 | fclose(tmp); | ||
108 | } | ||
109 | else | ||
110 | { | ||
111 | assert( ion >= 0 ); | ||
112 | close(ion); | ||
113 | ion = -1; | ||
114 | length = 0; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | bool HistoryBuffer::hasScroll() | ||
119 | { | ||
120 | return ion >= 0; | ||
121 | } | ||
122 | |||
123 | void HistoryBuffer::add(const unsigned char* bytes, int len) | ||
124 | { int rc; | ||
125 | assert(hasScroll()); | ||
126 | rc = lseek(ion,length,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::add.seek"); setScroll(FALSE); return; } | ||
127 | rc = write(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::add.write"); setScroll(FALSE); return; } | ||
128 | length += rc; | ||
129 | } | ||
130 | |||
131 | void HistoryBuffer::get(unsigned char* bytes, int len, int loc) | ||
132 | { int rc; | ||
133 | assert(hasScroll()); | ||
134 | if (loc < 0 || len < 0 || loc + len > length) | ||
135 | fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc); | ||
136 | rc = lseek(ion,loc,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::get.seek"); setScroll(FALSE); return; } | ||
137 | rc = read(ion,bytes,len); 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) | ||
167 | { | ||
168 | index.setScroll(on); | ||
169 | cells.setScroll(on); | ||
170 | } | ||
171 | |||
172 | bool HistoryScroll::hasScroll() | ||
173 | { | ||
174 | return index.hasScroll() && cells.hasScroll(); | ||
175 | } | ||
176 | |||
177 | int HistoryScroll::getLines() | ||
178 | { | ||
179 | if (!hasScroll()) return 0; | ||
180 | return index.len() / sizeof(int); | ||
181 | } | ||
182 | |||
183 | int HistoryScroll::getLineLen(int lineno) | ||
184 | { | ||
185 | if (!hasScroll()) return 0; | ||
186 | return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(Character); | ||
187 | } | ||
188 | |||
189 | int HistoryScroll::startOfLine(int lineno) | ||
190 | { | ||
191 | if (lineno <= 0) return 0; | ||
192 | if (!hasScroll()) return 0; | ||
193 | if (lineno <= getLines()) | ||
194 | { int res; | ||
195 | index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int)); | ||
196 | return res; | ||
197 | } | ||
198 | return cells.len(); | ||
199 | } | ||
200 | |||
201 | void HistoryScroll::getCells(int lineno, int colno, int count, Character res[]) | ||
202 | { | ||
203 | assert(hasScroll()); | ||
204 | cells.get((unsigned char*)res,count*sizeof(Character),startOfLine(lineno)+colno*sizeof(Character)); | ||
205 | } | ||
206 | |||
207 | void HistoryScroll::addCells(Character text[], int count) | ||
208 | { | ||
209 | if (!hasScroll()) return; | ||
210 | cells.add((unsigned char*)text,count*sizeof(Character)); | ||
211 | } | ||
212 | |||
213 | void HistoryScroll::addLine() | ||
214 | { | ||
215 | if (!hasScroll()) return; | ||
216 | int locn = cells.len(); | ||
217 | index.add((unsigned char*)&locn,sizeof(int)); | ||
218 | } | ||