00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "config.h"
00016 #include "vi.h"
00017
00018 #ifndef NBUFS
00019 # define NBUFS 5
00020 #endif
00021
00022
00023
00024
00025 BLK hdr;
00026
00027 static int b4cnt;
00028 static struct _blkbuf
00029 {
00030 BLK buf;
00031 unsigned short logical;
00032 int dirty;
00033 }
00034 blk[NBUFS],
00035 *toonew,
00036 *newtoo,
00037 *recycle = blk;
00038
00039
00040
00041
00042
00043
00044 void blkinit()
00045 {
00046 int i;
00047
00048 for (i = 0; i < NBUFS; i++)
00049 {
00050 blk[i].logical = 0;
00051 blk[i].dirty = FALSE;
00052 }
00053 for (i = 0; i < MAXBLKS; i++)
00054 {
00055 hdr.n[i] = 0;
00056 }
00057 }
00058
00059
00060 BLK *blkget(logical)
00061 int logical;
00062 {
00063 REG struct _blkbuf *this;
00064 REG int i;
00065
00066
00067 if (logical == 0)
00068 {
00069 return &hdr;
00070 }
00071
00072
00073 for (this = blk; this < &blk[NBUFS]; this++)
00074 {
00075 if (this->logical == logical)
00076 {
00077 newtoo = toonew;
00078 toonew = this;
00079 return &this->buf;
00080 }
00081 }
00082
00083
00084 do
00085 {
00086 this = recycle++;
00087 if (recycle == &blk[NBUFS])
00088 {
00089 recycle = blk;
00090 }
00091 } while (this == toonew || this == newtoo);
00092
00093
00094 blkflush(this);
00095
00096
00097 this->logical = logical;
00098 if (hdr.n[logical])
00099 {
00100
00101 lseek(tmpfd, (long)hdr.n[logical] * (long)BLKSIZE, 0);
00102 if (read(tmpfd, this->buf.c, (unsigned)BLKSIZE) != BLKSIZE)
00103 {
00104 msg("Error reading back from tmp file!");
00105 }
00106 }
00107 else
00108 {
00109
00110 for (i = 0; i < BLKSIZE; i++)
00111 {
00112 this->buf.c[i] = 0;
00113 }
00114 }
00115
00116
00117
00118
00119
00120 changes++;
00121
00122
00123 this->dirty = 0;
00124
00125
00126 newtoo = toonew;
00127 toonew = this;
00128 return &this->buf;
00129 }
00130
00131
00132
00133
00134 void blkflush(this)
00135 REG struct _blkbuf *this;
00136 {
00137 long seekpos;
00138 unsigned short physical;
00139
00140
00141 if (this->logical && !*this->buf.c)
00142 {
00143 blkdirty(&this->buf);
00144 }
00145
00146
00147 if (!this->logical || hdr.n[this->logical] && !this->dirty)
00148 {
00149 return;
00150 }
00151
00152
00153 #ifndef NO_RECYCLE
00154 seekpos = allocate();
00155 lseek(tmpfd, seekpos, 0);
00156 #else
00157 seekpos = lseek(tmpfd, 0L, 2);
00158 #endif
00159 physical = seekpos / BLKSIZE;
00160
00161
00162 if (write(tmpfd, this->buf.c, (unsigned)BLKSIZE) != BLKSIZE)
00163 {
00164 msg("Trouble writing to tmp file");
00165 }
00166 this->dirty = FALSE;
00167
00168
00169 hdr.n[this->logical] = physical;
00170 }
00171
00172
00173
00174 void blkdirty(bp)
00175 BLK *bp;
00176 {
00177 REG int i, j;
00178 REG char *scan;
00179 REG int k;
00180
00181
00182 for (i = 0; i < NBUFS && bp != &blk[i].buf; i++)
00183 {
00184 }
00185 #ifdef DEBUG
00186 if (i >= NBUFS)
00187 {
00188 msg("blkdirty() called with unknown buffer at 0x%lx", bp);
00189 return;
00190 }
00191 if (blk[i].logical == 0)
00192 {
00193 msg("blkdirty called with freed buffer");
00194 return;
00195 }
00196 #endif
00197
00198
00199
00200
00201 if (lnum[blk[i].logical] == INFINITY)
00202 {
00203 #ifdef DEBUG
00204 if (blk[i].buf.c[0])
00205 {
00206 msg("bkldirty called with non-empty extra BLK");
00207 }
00208 #endif
00209 blk[i].logical = 0;
00210 blk[i].dirty = FALSE;
00211 return;
00212 }
00213
00214
00215 for (j = 0, scan = bp->c; *scan && scan < bp->c + BLKSIZE; scan++)
00216 {
00217 if (*scan == '\n')
00218 {
00219 j++;
00220 }
00221 }
00222
00223
00224 k = blk[i].logical;
00225 j += (lnum[k - 1] - lnum[k]);
00226 if (j != 0)
00227 {
00228 nlines += j;
00229 while (k < MAXBLKS && lnum[k] != INFINITY)
00230 {
00231 lnum[k++] += j;
00232 }
00233 }
00234
00235
00236 if (*bp->c)
00237 {
00238 blk[i].dirty = TRUE;
00239 }
00240 else
00241 {
00242
00243 k = blk[i].logical;
00244 for (j = 0; j < NBUFS; j++)
00245 {
00246 if (blk[j].logical >= k)
00247 {
00248 blk[j].logical--;
00249 }
00250 }
00251
00252
00253 blk[i].logical = 0;
00254 blk[i].dirty = FALSE;
00255 while (k < MAXBLKS - 1)
00256 {
00257 hdr.n[k] = hdr.n[k + 1];
00258 lnum[k] = lnum[k + 1];
00259 k++;
00260 }
00261 hdr.n[MAXBLKS - 1] = 0;
00262 lnum[MAXBLKS - 1] = INFINITY;
00263 }
00264 }
00265
00266
00267
00268 BLK *blkadd(logical)
00269 int logical;
00270 {
00271 REG int i;
00272
00273
00274 for (i = MAXBLKS - 1; i > logical; i--)
00275 {
00276 hdr.n[i] = hdr.n[i - 1];
00277 lnum[i] = lnum[i - 1];
00278 }
00279 hdr.n[logical] = 0;
00280 lnum[logical] = lnum[logical - 1];
00281
00282
00283 for (i = 0; i < NBUFS; i++)
00284 {
00285 if (blk[i].logical >= logical)
00286 {
00287 blk[i].logical++;
00288 }
00289 }
00290
00291
00292 return blkget(logical);
00293 }
00294
00295
00296
00297 void blksync()
00298 {
00299 int i;
00300
00301 for (i = 0; i < NBUFS; i++)
00302 {
00303
00304 blkflush(&blk[i]);
00305 }
00306 if (*o_sync)
00307 {
00308 sync();
00309 }
00310 }
00311
00312
00313
00314 static MARK undocurs;
00315 static long oldnlines;
00316 static long oldlnum[MAXBLKS];
00317
00318
00319
00320
00321
00322 void beforedo(forundo)
00323 int forundo;
00324 {
00325 REG int i;
00326 REG long l;
00327
00328
00329 if (b4cnt++ > 0)
00330 {
00331 return;
00332 }
00333
00334
00335 blksync();
00336
00337 #ifndef NO_RECYCLE
00338
00339 garbage();
00340 #endif
00341
00342
00343 lseek(tmpfd, 0L, 0);
00344 if (write(tmpfd, hdr.c, (unsigned)BLKSIZE) != BLKSIZE)
00345 {
00346 msg("Trouble writing header to tmp file ");
00347 }
00348
00349
00350 if (forundo)
00351 {
00352 for (i = 0; i < MAXBLKS; i++)
00353 {
00354 l = lnum[i];
00355 lnum[i] = oldlnum[i];
00356 oldlnum[i] = l;
00357 }
00358 l = nlines;
00359 nlines = oldnlines;
00360 oldnlines = l;
00361 }
00362 else
00363 {
00364 for (i = 0; i < MAXBLKS; i++)
00365 {
00366 oldlnum[i] = lnum[i];
00367 }
00368 oldnlines = nlines;
00369 }
00370
00371
00372 undocurs = cursor;
00373
00374
00375 }
00376
00377
00378 void afterdo()
00379 {
00380 if (--b4cnt)
00381 {
00382
00383
00384
00385
00386 if (b4cnt < 0)
00387 b4cnt = 0;
00388
00389 return;
00390 }
00391
00392
00393 if (markline(cursor) > nlines)
00394 {
00395 cursor = MARK_LAST;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404 if (significant)
00405 {
00406 setflag(file, MODIFIED);
00407 setflag(file, UNDOABLE);
00408 }
00409 }
00410
00411
00412
00413
00414 void abortdo()
00415 {
00416
00417 if (b4cnt > 0)
00418 {
00419 b4cnt = 1;
00420 afterdo();
00421 }
00422
00423
00424 if (mode == MODE_COLON)
00425 {
00426 mode = MODE_VI;
00427 }
00428 if (mode == MODE_VI)
00429 {
00430 redraw(MARK_UNSET, FALSE);
00431 }
00432 }
00433
00434
00435 int undo()
00436 {
00437 BLK oldhdr;
00438
00439
00440 if (!tstflag(file, UNDOABLE))
00441 {
00442 msg("You haven't modified this file yet.");
00443 return FALSE;
00444 }
00445
00446
00447 lseek(tmpfd, 0L, 0);
00448 if (read(tmpfd, oldhdr.c, (unsigned)BLKSIZE) != BLKSIZE)
00449 {
00450 msg("Trouble rereading the old header from tmp file");
00451 }
00452
00453
00454 cursor = undocurs;
00455 beforedo(TRUE);
00456 afterdo();
00457
00458
00459 blkinit();
00460
00461
00462 hdr = oldhdr;
00463
00464
00465 significant = TRUE;
00466 changes++;
00467
00468 return TRUE;
00469 }