Diffstat (limited to 'noncore/apps/opie-console/TEHistory.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/apps/opie-console/TEHistory.cpp | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/noncore/apps/opie-console/TEHistory.cpp b/noncore/apps/opie-console/TEHistory.cpp new file mode 100644 index 0000000..317ce57 --- a/dev/null +++ b/noncore/apps/opie-console/TEHistory.cpp | |||
@@ -0,0 +1,212 @@ | |||
1 | /* -------------------------------------------------------------------------- */ | ||
2 | /* */ | ||
3 | /* [TEHistory.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 | #include "TEHistory.h" | ||
20 | #include <stdlib.h> | ||
21 | #include <assert.h> | ||
22 | #include <stdio.h> | ||
23 | #include <sys/types.h> | ||
24 | #include <unistd.h> | ||
25 | #include <errno.h> | ||
26 | |||
27 | #define HERE printf("%s(%d): here\n",__FILE__,__LINE__) | ||
28 | |||
29 | /* | ||
30 | An arbitrary long scroll. | ||
31 | |||
32 | One can modify the scroll only by adding either cells | ||
33 | or newlines, but access it randomly. | ||
34 | |||
35 | The model is that of an arbitrary wide typewriter scroll | ||
36 | in that the scroll is a serie of lines and each line is | ||
37 | a serie of cells with no overwriting permitted. | ||
38 | |||
39 | The implementation provides arbitrary length and numbers | ||
40 | of cells and line/column indexed read access to the scroll | ||
41 | at constant costs. | ||
42 | |||
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 | */ | ||
59 | |||
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 | |||
74 | // History Buffer /////////////////////////////////////////// | ||
75 | |||
76 | /* | ||
77 | A Row(X) data type which allows adding elements to the end. | ||
78 | */ | ||
79 | |||
80 | HistoryBuffer::HistoryBuffer() | ||
81 | { | ||
82 | ion = -1; | ||
83 | length = 0; | ||
84 | } | ||
85 | |||
86 | HistoryBuffer::~HistoryBuffer() | ||
87 | { | ||
88 | setScroll(FALSE); | ||
89 | } | ||
90 | |||
91 | void HistoryBuffer::setScroll(bool on) | ||
92 | { | ||
93 | if (on == hasScroll()) return; | ||
94 | |||
95 | if (on) | ||
96 | { | ||
97 | assert( ion < 0 ); | ||
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 | } | ||
103 | else | ||
104 | { | ||
105 | assert( ion >= 0 ); | ||
106 | close(ion); | ||
107 | ion = -1; | ||
108 | length = 0; | ||
109 | } | ||
110 | } | ||
111 | |||
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); if (rc < 0) { perror("HistoryBuffer::add.seek"); setScroll(FALSE); return; } | ||
121 | rc = write(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::add.write"); setScroll(FALSE); return; } | ||
122 | length += rc; | ||
123 | } | ||
124 | |||
125 | void HistoryBuffer::get(unsigned char* bytes, int len, int loc) | ||
126 | { int rc; | ||
127 | assert(hasScroll()); | ||
128 | if (loc < 0 || len < 0 || loc + len > length) | ||
129 | fprintf(stderr,"getHist(...,%d,%d): invalid args.\n",len,loc); | ||
130 | rc = lseek(ion,loc,SEEK_SET); if (rc < 0) { perror("HistoryBuffer::get.seek"); setScroll(FALSE); return; } | ||
131 | rc = read(ion,bytes,len); if (rc < 0) { perror("HistoryBuffer::get.read"); setScroll(FALSE); return; } | ||
132 | } | ||
133 | |||
134 | int HistoryBuffer::len() | ||
135 | { | ||
136 | return length; | ||
137 | } | ||
138 | |||
139 | // History Scroll ////////////////////////////////////// | ||
140 | |||
141 | /* | ||
142 | The history scroll makes a Row(Row(Cell)) from | ||
143 | two history buffers. The index buffer contains | ||
144 | start of line positions which refere to the cells | ||
145 | buffer. | ||
146 | |||
147 | Note that index[0] addresses the second line | ||
148 | (line #1), while the first line (line #0) starts | ||
149 | at 0 in cells. | ||
150 | */ | ||
151 | |||
152 | HistoryScroll::HistoryScroll() | ||
153 | { | ||
154 | } | ||
155 | |||
156 | HistoryScroll::~HistoryScroll() | ||
157 | { | ||
158 | } | ||
159 | |||
160 | void HistoryScroll::setScroll(bool on) | ||
161 | { | ||
162 | index.setScroll(on); | ||
163 | cells.setScroll(on); | ||
164 | } | ||
165 | |||
166 | bool HistoryScroll::hasScroll() | ||
167 | { | ||
168 | return index.hasScroll() && cells.hasScroll(); | ||
169 | } | ||
170 | |||
171 | int HistoryScroll::getLines() | ||
172 | { | ||
173 | if (!hasScroll()) return 0; | ||
174 | return index.len() / sizeof(int); | ||
175 | } | ||
176 | |||
177 | int HistoryScroll::getLineLen(int lineno) | ||
178 | { | ||
179 | if (!hasScroll()) return 0; | ||
180 | return (startOfLine(lineno+1) - startOfLine(lineno)) / sizeof(ca); | ||
181 | } | ||
182 | |||
183 | int HistoryScroll::startOfLine(int lineno) | ||
184 | { | ||
185 | if (lineno <= 0) return 0; | ||
186 | if (!hasScroll()) return 0; | ||
187 | if (lineno <= getLines()) | ||
188 | { int res; | ||
189 | index.get((unsigned char*)&res,sizeof(int),(lineno-1)*sizeof(int)); | ||
190 | return res; | ||
191 | } | ||
192 | return cells.len(); | ||
193 | } | ||
194 | |||
195 | void HistoryScroll::getCells(int lineno, int colno, int count, ca res[]) | ||
196 | { | ||
197 | assert(hasScroll()); | ||
198 | cells.get((unsigned char*)res,count*sizeof(ca),startOfLine(lineno)+colno*sizeof(ca)); | ||
199 | } | ||
200 | |||
201 | void HistoryScroll::addCells(ca text[], int count) | ||
202 | { | ||
203 | if (!hasScroll()) return; | ||
204 | cells.add((unsigned char*)text,count*sizeof(ca)); | ||
205 | } | ||
206 | |||
207 | void HistoryScroll::addLine() | ||
208 | { | ||
209 | if (!hasScroll()) return; | ||
210 | int locn = cells.len(); | ||
211 | index.add((unsigned char*)&locn,sizeof(int)); | ||
212 | } | ||