119304Speter/*- 219304Speter * Copyright (c) 1992, 1993, 1994 319304Speter * The Regents of the University of California. All rights reserved. 419304Speter * Copyright (c) 1992, 1993, 1994, 1995, 1996 519304Speter * Keith Bostic. All rights reserved. 619304Speter * 719304Speter * See the LICENSE file for redistribution information. 819304Speter */ 919304Speter 1019304Speter#include "config.h" 1119304Speter 1219304Speter#ifndef lint 13254225Speterstatic const char sccsid[] = "$Id: line.c,v 10.26 2011/08/12 12:36:41 zy Exp $"; 1419304Speter#endif /* not lint */ 1519304Speter 1619304Speter#include <sys/types.h> 1719304Speter#include <sys/queue.h> 1819304Speter#include <sys/time.h> 1919304Speter 2019304Speter#include <bitstring.h> 2119304Speter#include <errno.h> 2219304Speter#include <limits.h> 2319304Speter#include <stdio.h> 2419304Speter#include <string.h> 2519304Speter 2619304Speter#include "common.h" 2719304Speter#include "../vi/vi.h" 2819304Speter 2919304Speterstatic int scr_update __P((SCR *, recno_t, lnop_t, int)); 3019304Speter 3119304Speter/* 3219304Speter * db_eget -- 3319304Speter * Front-end to db_get, special case handling for empty files. 3419304Speter * 35254225Speter * PUBLIC: int db_eget __P((SCR *, recno_t, CHAR_T **, size_t *, int *)); 3619304Speter */ 3719304Speterint 38254225Speterdb_eget( 39254225Speter SCR *sp, 40254225Speter recno_t lno, /* Line number. */ 41254225Speter CHAR_T **pp, /* Pointer store. */ 42254225Speter size_t *lenp, /* Length store. */ 43254225Speter int *isemptyp) 4419304Speter{ 4519304Speter recno_t l1; 4619304Speter 4719304Speter if (isemptyp != NULL) 4819304Speter *isemptyp = 0; 4919304Speter 5019304Speter /* If the line exists, simply return it. */ 5119304Speter if (!db_get(sp, lno, 0, pp, lenp)) 5219304Speter return (0); 5319304Speter 5419304Speter /* 5519304Speter * If the user asked for line 0 or line 1, i.e. the only possible 5619304Speter * line in an empty file, find the last line of the file; db_last 5719304Speter * fails loudly. 5819304Speter */ 5919304Speter if ((lno == 0 || lno == 1) && db_last(sp, &l1)) 6019304Speter return (1); 6119304Speter 6219304Speter /* If the file isn't empty, fail loudly. */ 63254225Speter if ((lno != 0 && lno != 1) || l1 != 0) { 6419304Speter db_err(sp, lno); 6519304Speter return (1); 6619304Speter } 6719304Speter 6819304Speter if (isemptyp != NULL) 6919304Speter *isemptyp = 1; 7019304Speter 7119304Speter return (1); 7219304Speter} 7319304Speter 7419304Speter/* 7519304Speter * db_get -- 7619304Speter * Look in the text buffers for a line, followed by the cache, followed 7719304Speter * by the database. 7819304Speter * 79254225Speter * PUBLIC: int db_get __P((SCR *, recno_t, u_int32_t, CHAR_T **, size_t *)); 8019304Speter */ 8119304Speterint 82254225Speterdb_get( 83254225Speter SCR *sp, 84254225Speter recno_t lno, /* Line number. */ 85254225Speter u_int32_t flags, 86254225Speter CHAR_T **pp, /* Pointer store. */ 87254225Speter size_t *lenp) /* Length store. */ 8819304Speter{ 8919304Speter DBT data, key; 9019304Speter EXF *ep; 9119304Speter TEXT *tp; 9219304Speter recno_t l1, l2; 93254225Speter CHAR_T *wp; 94254225Speter size_t wlen; 95254225Speter size_t nlen; 9619304Speter 9719304Speter /* 9819304Speter * The underlying recno stuff handles zero by returning NULL, but 9919304Speter * have to have an OOB condition for the look-aside into the input 10019304Speter * buffer anyway. 10119304Speter */ 10219304Speter if (lno == 0) 10319304Speter goto err1; 10419304Speter 10519304Speter /* Check for no underlying file. */ 10619304Speter if ((ep = sp->ep) == NULL) { 10719304Speter ex_emsg(sp, NULL, EXM_NOFILEYET); 10819304Speter goto err3; 10919304Speter } 11019304Speter 11119304Speter if (LF_ISSET(DBG_NOCACHE)) 11219304Speter goto nocache; 11319304Speter 11419304Speter /* 11519304Speter * Look-aside into the TEXT buffers and see if the line we want 11619304Speter * is there. 11719304Speter */ 11819304Speter if (F_ISSET(sp, SC_TINPUT)) { 119254225Speter l1 = ((TEXT *)TAILQ_FIRST(sp->tiq))->lno; 120254225Speter l2 = ((TEXT *)TAILQ_LAST(sp->tiq, _texth))->lno; 12119304Speter if (l1 <= lno && l2 >= lno) { 12219304Speter#if defined(DEBUG) && 0 12319304Speter TRACE(sp, "retrieve TEXT buffer line %lu\n", (u_long)lno); 12419304Speter#endif 125254225Speter for (tp = TAILQ_FIRST(sp->tiq); 126254225Speter tp->lno != lno; tp = TAILQ_NEXT(tp, q)); 12719304Speter if (lenp != NULL) 12819304Speter *lenp = tp->len; 12919304Speter if (pp != NULL) 13019304Speter *pp = tp->lb; 13119304Speter return (0); 13219304Speter } 13319304Speter /* 13419304Speter * Adjust the line number for the number of lines used 13519304Speter * by the text input buffers. 13619304Speter */ 13719304Speter if (lno > l2) 13819304Speter lno -= l2 - l1; 13919304Speter } 14019304Speter 14119304Speter /* Look-aside into the cache, and see if the line we want is there. */ 14219304Speter if (lno == ep->c_lno) { 14319304Speter#if defined(DEBUG) && 0 14419304Speter TRACE(sp, "retrieve cached line %lu\n", (u_long)lno); 14519304Speter#endif 14619304Speter if (lenp != NULL) 14719304Speter *lenp = ep->c_len; 14819304Speter if (pp != NULL) 14919304Speter *pp = ep->c_lp; 15019304Speter return (0); 15119304Speter } 15219304Speter ep->c_lno = OOBLNO; 15319304Speter 15419304Speternocache: 155254225Speter nlen = 1024; 156254225Speterretry: 15719304Speter /* Get the line from the underlying database. */ 15819304Speter key.data = &lno; 15919304Speter key.size = sizeof(lno); 16019304Speter switch (ep->db->get(ep->db, &key, &data, 0)) { 161254225Speter case -1: 16219304Speter goto err2; 16319304Speter case 1: 16419304Spetererr1: if (LF_ISSET(DBG_FATAL)) 16519304Spetererr2: db_err(sp, lno); 166254225Speteralloc_err: 16719304Spetererr3: if (lenp != NULL) 16819304Speter *lenp = 0; 16919304Speter if (pp != NULL) 17019304Speter *pp = NULL; 17119304Speter return (1); 172254225Speter case 0: 173254225Speter if (data.size > nlen) { 174254225Speter nlen = data.size; 175254225Speter goto retry; 176254225Speter } 17719304Speter } 17819304Speter 179254225Speter if (FILE2INT(sp, data.data, data.size, wp, wlen)) { 180254225Speter if (!F_ISSET(sp, SC_CONV_ERROR)) { 181254225Speter F_SET(sp, SC_CONV_ERROR); 182254225Speter msgq(sp, M_ERR, "324|Conversion error on line %d", lno); 183254225Speter } 184254225Speter goto err3; 185254225Speter } 186254225Speter 18719304Speter /* Reset the cache. */ 188254225Speter if (wp != data.data) { 189254225Speter BINC_GOTOW(sp, ep->c_lp, ep->c_blen, wlen); 190254225Speter MEMCPY(ep->c_lp, wp, wlen); 191254225Speter } else 192254225Speter ep->c_lp = data.data; 19319304Speter ep->c_lno = lno; 194254225Speter ep->c_len = wlen; 19519304Speter 19619304Speter#if defined(DEBUG) && 0 19719304Speter TRACE(sp, "retrieve DB line %lu\n", (u_long)lno); 19819304Speter#endif 19919304Speter if (lenp != NULL) 200254225Speter *lenp = wlen; 20119304Speter if (pp != NULL) 20219304Speter *pp = ep->c_lp; 20319304Speter return (0); 20419304Speter} 20519304Speter 20619304Speter/* 20719304Speter * db_delete -- 20819304Speter * Delete a line from the file. 20919304Speter * 21019304Speter * PUBLIC: int db_delete __P((SCR *, recno_t)); 21119304Speter */ 21219304Speterint 213254225Speterdb_delete( 214254225Speter SCR *sp, 215254225Speter recno_t lno) 21619304Speter{ 21719304Speter DBT key; 21819304Speter EXF *ep; 21919304Speter 22019304Speter#if defined(DEBUG) && 0 22119304Speter TRACE(sp, "delete line %lu\n", (u_long)lno); 22219304Speter#endif 22319304Speter /* Check for no underlying file. */ 22419304Speter if ((ep = sp->ep) == NULL) { 22519304Speter ex_emsg(sp, NULL, EXM_NOFILEYET); 22619304Speter return (1); 22719304Speter } 22819304Speter 22919304Speter /* Update marks, @ and global commands. */ 23019304Speter if (mark_insdel(sp, LINE_DELETE, lno)) 23119304Speter return (1); 23219304Speter if (ex_g_insdel(sp, LINE_DELETE, lno)) 23319304Speter return (1); 23419304Speter 23519304Speter /* Log change. */ 23619304Speter log_line(sp, lno, LOG_LINE_DELETE); 23719304Speter 23819304Speter /* Update file. */ 23919304Speter key.data = &lno; 24019304Speter key.size = sizeof(lno); 24119304Speter SIGBLOCK; 24219304Speter if (ep->db->del(ep->db, &key, 0) == 1) { 24319304Speter msgq(sp, M_SYSERR, 24419304Speter "003|unable to delete line %lu", (u_long)lno); 24519304Speter return (1); 24619304Speter } 24719304Speter SIGUNBLOCK; 24819304Speter 24919304Speter /* Flush the cache, update line count, before screen update. */ 25019304Speter if (lno <= ep->c_lno) 25119304Speter ep->c_lno = OOBLNO; 25219304Speter if (ep->c_nlines != OOBLNO) 25319304Speter --ep->c_nlines; 25419304Speter 25519304Speter /* File now modified. */ 25619304Speter if (F_ISSET(ep, F_FIRSTMODIFY)) 25719304Speter (void)rcv_init(sp); 25819304Speter F_SET(ep, F_MODIFIED); 25919304Speter 26019304Speter /* Update screen. */ 26119304Speter return (scr_update(sp, lno, LINE_DELETE, 1)); 26219304Speter} 26319304Speter 26419304Speter/* 26519304Speter * db_append -- 26619304Speter * Append a line into the file. 26719304Speter * 268254225Speter * PUBLIC: int db_append __P((SCR *, int, recno_t, CHAR_T *, size_t)); 26919304Speter */ 27019304Speterint 271254225Speterdb_append( 272254225Speter SCR *sp, 273254225Speter int update, 274254225Speter recno_t lno, 275254225Speter CHAR_T *p, 276254225Speter size_t len) 27719304Speter{ 27819304Speter DBT data, key; 27919304Speter EXF *ep; 280254225Speter char *fp; 281254225Speter size_t flen; 28219304Speter int rval; 28319304Speter 28419304Speter#if defined(DEBUG) && 0 28519304Speter TRACE(sp, "append to %lu: len %u {%.*s}\n", lno, len, MIN(len, 20), p); 28619304Speter#endif 28719304Speter /* Check for no underlying file. */ 28819304Speter if ((ep = sp->ep) == NULL) { 28919304Speter ex_emsg(sp, NULL, EXM_NOFILEYET); 29019304Speter return (1); 29119304Speter } 29219304Speter 293254225Speter INT2FILE(sp, p, len, fp, flen); 294254225Speter 29519304Speter /* Update file. */ 29619304Speter key.data = &lno; 29719304Speter key.size = sizeof(lno); 298254225Speter data.data = fp; 299254225Speter data.size = flen; 30019304Speter SIGBLOCK; 30119304Speter if (ep->db->put(ep->db, &key, &data, R_IAFTER) == -1) { 30219304Speter msgq(sp, M_SYSERR, 30319304Speter "004|unable to append to line %lu", (u_long)lno); 30419304Speter return (1); 30519304Speter } 30619304Speter SIGUNBLOCK; 30719304Speter 30819304Speter /* Flush the cache, update line count, before screen update. */ 30919304Speter if (lno < ep->c_lno) 31019304Speter ep->c_lno = OOBLNO; 31119304Speter if (ep->c_nlines != OOBLNO) 31219304Speter ++ep->c_nlines; 31319304Speter 31419304Speter /* File now dirty. */ 31519304Speter if (F_ISSET(ep, F_FIRSTMODIFY)) 31619304Speter (void)rcv_init(sp); 31719304Speter F_SET(ep, F_MODIFIED); 31819304Speter 31919304Speter /* Log change. */ 32019304Speter log_line(sp, lno + 1, LOG_LINE_APPEND); 32119304Speter 32219304Speter /* Update marks, @ and global commands. */ 32319304Speter rval = 0; 32419304Speter if (mark_insdel(sp, LINE_INSERT, lno + 1)) 32519304Speter rval = 1; 32619304Speter if (ex_g_insdel(sp, LINE_INSERT, lno + 1)) 32719304Speter rval = 1; 32819304Speter 32919304Speter /* 33019304Speter * Update screen. 33119304Speter * 33219304Speter * XXX 33319304Speter * Nasty hack. If multiple lines are input by the user, they aren't 33419304Speter * committed until an <ESC> is entered. The problem is the screen was 33519304Speter * updated/scrolled as each line was entered. So, when this routine 33619304Speter * is called to copy the new lines from the cut buffer into the file, 33719304Speter * it has to know not to update the screen again. 33819304Speter */ 33919304Speter return (scr_update(sp, lno, LINE_APPEND, update) || rval); 34019304Speter} 34119304Speter 34219304Speter/* 34319304Speter * db_insert -- 34419304Speter * Insert a line into the file. 34519304Speter * 346254225Speter * PUBLIC: int db_insert __P((SCR *, recno_t, CHAR_T *, size_t)); 34719304Speter */ 34819304Speterint 349254225Speterdb_insert( 350254225Speter SCR *sp, 351254225Speter recno_t lno, 352254225Speter CHAR_T *p, 353254225Speter size_t len) 35419304Speter{ 35519304Speter DBT data, key; 35619304Speter EXF *ep; 357254225Speter char *fp; 358254225Speter size_t flen; 35919304Speter int rval; 36019304Speter 36119304Speter#if defined(DEBUG) && 0 36219304Speter TRACE(sp, "insert before %lu: len %lu {%.*s}\n", 36319304Speter (u_long)lno, (u_long)len, MIN(len, 20), p); 36419304Speter#endif 36519304Speter /* Check for no underlying file. */ 36619304Speter if ((ep = sp->ep) == NULL) { 36719304Speter ex_emsg(sp, NULL, EXM_NOFILEYET); 36819304Speter return (1); 36919304Speter } 37019304Speter 371254225Speter INT2FILE(sp, p, len, fp, flen); 372254225Speter 37319304Speter /* Update file. */ 37419304Speter key.data = &lno; 37519304Speter key.size = sizeof(lno); 376254225Speter data.data = fp; 377254225Speter data.size = flen; 37819304Speter SIGBLOCK; 37919304Speter if (ep->db->put(ep->db, &key, &data, R_IBEFORE) == -1) { 38019304Speter msgq(sp, M_SYSERR, 38119304Speter "005|unable to insert at line %lu", (u_long)lno); 38219304Speter return (1); 38319304Speter } 38419304Speter SIGUNBLOCK; 38519304Speter 38619304Speter /* Flush the cache, update line count, before screen update. */ 38719304Speter if (lno >= ep->c_lno) 38819304Speter ep->c_lno = OOBLNO; 38919304Speter if (ep->c_nlines != OOBLNO) 39019304Speter ++ep->c_nlines; 39119304Speter 39219304Speter /* File now dirty. */ 39319304Speter if (F_ISSET(ep, F_FIRSTMODIFY)) 39419304Speter (void)rcv_init(sp); 39519304Speter F_SET(ep, F_MODIFIED); 39619304Speter 39719304Speter /* Log change. */ 39819304Speter log_line(sp, lno, LOG_LINE_INSERT); 39919304Speter 40019304Speter /* Update marks, @ and global commands. */ 40119304Speter rval = 0; 40219304Speter if (mark_insdel(sp, LINE_INSERT, lno)) 40319304Speter rval = 1; 40419304Speter if (ex_g_insdel(sp, LINE_INSERT, lno)) 40519304Speter rval = 1; 40619304Speter 40719304Speter /* Update screen. */ 40819304Speter return (scr_update(sp, lno, LINE_INSERT, 1) || rval); 40919304Speter} 41019304Speter 41119304Speter/* 41219304Speter * db_set -- 41319304Speter * Store a line in the file. 41419304Speter * 415254225Speter * PUBLIC: int db_set __P((SCR *, recno_t, CHAR_T *, size_t)); 41619304Speter */ 41719304Speterint 418254225Speterdb_set( 419254225Speter SCR *sp, 420254225Speter recno_t lno, 421254225Speter CHAR_T *p, 422254225Speter size_t len) 42319304Speter{ 42419304Speter DBT data, key; 42519304Speter EXF *ep; 426254225Speter char *fp; 427254225Speter size_t flen; 42819304Speter 42919304Speter#if defined(DEBUG) && 0 43019304Speter TRACE(sp, "replace line %lu: len %lu {%.*s}\n", 43119304Speter (u_long)lno, (u_long)len, MIN(len, 20), p); 43219304Speter#endif 43319304Speter /* Check for no underlying file. */ 43419304Speter if ((ep = sp->ep) == NULL) { 43519304Speter ex_emsg(sp, NULL, EXM_NOFILEYET); 43619304Speter return (1); 43719304Speter } 43819304Speter 43919304Speter /* Log before change. */ 44019304Speter log_line(sp, lno, LOG_LINE_RESET_B); 44119304Speter 442254225Speter INT2FILE(sp, p, len, fp, flen); 443254225Speter 44419304Speter /* Update file. */ 44519304Speter key.data = &lno; 44619304Speter key.size = sizeof(lno); 447254225Speter data.data = fp; 448254225Speter data.size = flen; 44919304Speter SIGBLOCK; 45019304Speter if (ep->db->put(ep->db, &key, &data, 0) == -1) { 45119304Speter msgq(sp, M_SYSERR, 45219304Speter "006|unable to store line %lu", (u_long)lno); 45319304Speter return (1); 45419304Speter } 45519304Speter SIGUNBLOCK; 45619304Speter 45719304Speter /* Flush the cache, before logging or screen update. */ 45819304Speter if (lno == ep->c_lno) 45919304Speter ep->c_lno = OOBLNO; 46019304Speter 46119304Speter /* File now dirty. */ 46219304Speter if (F_ISSET(ep, F_FIRSTMODIFY)) 46319304Speter (void)rcv_init(sp); 46419304Speter F_SET(ep, F_MODIFIED); 46519304Speter 46619304Speter /* Log after change. */ 46719304Speter log_line(sp, lno, LOG_LINE_RESET_F); 46819304Speter 46919304Speter /* Update screen. */ 47019304Speter return (scr_update(sp, lno, LINE_RESET, 1)); 47119304Speter} 47219304Speter 47319304Speter/* 47419304Speter * db_exist -- 47519304Speter * Return if a line exists. 47619304Speter * 47719304Speter * PUBLIC: int db_exist __P((SCR *, recno_t)); 47819304Speter */ 47919304Speterint 480254225Speterdb_exist( 481254225Speter SCR *sp, 482254225Speter recno_t lno) 48319304Speter{ 48419304Speter EXF *ep; 48519304Speter 48619304Speter /* Check for no underlying file. */ 48719304Speter if ((ep = sp->ep) == NULL) { 48819304Speter ex_emsg(sp, NULL, EXM_NOFILEYET); 48919304Speter return (1); 49019304Speter } 49119304Speter 49219304Speter if (lno == OOBLNO) 49319304Speter return (0); 49419304Speter 49519304Speter /* 49619304Speter * Check the last-line number cache. Adjust the cached line 49719304Speter * number for the lines used by the text input buffers. 49819304Speter */ 49919304Speter if (ep->c_nlines != OOBLNO) 50019304Speter return (lno <= (F_ISSET(sp, SC_TINPUT) ? 501254225Speter ep->c_nlines + (((TEXT *)TAILQ_LAST(sp->tiq, _texth))->lno - 502254225Speter ((TEXT *)TAILQ_FIRST(sp->tiq))->lno) : ep->c_nlines)); 50319304Speter 50419304Speter /* Go get the line. */ 50519304Speter return (!db_get(sp, lno, 0, NULL, NULL)); 50619304Speter} 50719304Speter 50819304Speter/* 50919304Speter * db_last -- 51019304Speter * Return the number of lines in the file. 51119304Speter * 51219304Speter * PUBLIC: int db_last __P((SCR *, recno_t *)); 51319304Speter */ 51419304Speterint 515254225Speterdb_last( 516254225Speter SCR *sp, 517254225Speter recno_t *lnop) 51819304Speter{ 51919304Speter DBT data, key; 52019304Speter EXF *ep; 52119304Speter recno_t lno; 522254225Speter CHAR_T *wp; 523254225Speter size_t wlen; 52419304Speter 52519304Speter /* Check for no underlying file. */ 52619304Speter if ((ep = sp->ep) == NULL) { 52719304Speter ex_emsg(sp, NULL, EXM_NOFILEYET); 52819304Speter return (1); 52919304Speter } 53019304Speter 53119304Speter /* 53219304Speter * Check the last-line number cache. Adjust the cached line 53319304Speter * number for the lines used by the text input buffers. 53419304Speter */ 53519304Speter if (ep->c_nlines != OOBLNO) { 53619304Speter *lnop = ep->c_nlines; 53719304Speter if (F_ISSET(sp, SC_TINPUT)) 538254225Speter *lnop += ((TEXT *)TAILQ_LAST(sp->tiq, _texth))->lno - 539254225Speter ((TEXT *)TAILQ_FIRST(sp->tiq))->lno; 54019304Speter return (0); 54119304Speter } 54219304Speter 54319304Speter key.data = &lno; 54419304Speter key.size = sizeof(lno); 54519304Speter 54619304Speter switch (ep->db->seq(ep->db, &key, &data, R_LAST)) { 547254225Speter case -1: 548254225Speteralloc_err: 54919304Speter msgq(sp, M_SYSERR, "007|unable to get last line"); 55019304Speter *lnop = 0; 55119304Speter return (1); 552254225Speter case 1: 55319304Speter *lnop = 0; 55419304Speter return (0); 555254225Speter case 0: 556254225Speter ; 55719304Speter } 55819304Speter 55919304Speter memcpy(&lno, key.data, sizeof(lno)); 56019304Speter 561254225Speter if (lno != ep->c_lno) { 562254225Speter FILE2INT(sp, data.data, data.size, wp, wlen); 563254225Speter 564254225Speter /* Fill the cache. */ 565254225Speter if (wp != data.data) { 566254225Speter BINC_GOTOW(sp, ep->c_lp, ep->c_blen, wlen); 567254225Speter MEMCPY(ep->c_lp, wp, wlen); 568254225Speter } else 569254225Speter ep->c_lp = data.data; 570254225Speter ep->c_lno = lno; 571254225Speter ep->c_len = wlen; 572254225Speter } 573254225Speter ep->c_nlines = lno; 574254225Speter 57519304Speter /* Return the value. */ 57619304Speter *lnop = (F_ISSET(sp, SC_TINPUT) && 577254225Speter ((TEXT *)TAILQ_LAST(sp->tiq, _texth))->lno > lno ? 578254225Speter ((TEXT *)TAILQ_LAST(sp->tiq, _texth))->lno : lno); 57919304Speter return (0); 58019304Speter} 58119304Speter 58219304Speter/* 583254225Speter * db_rget -- 584254225Speter * Retrieve a raw line from database. No cache, no conversion. 585254225Speter * 586254225Speter * PUBLIC: int db_rget __P((SCR *, recno_t, char **, size_t *)); 587254225Speter */ 588254225Speterint 589254225Speterdb_rget( 590254225Speter SCR *sp, 591254225Speter recno_t lno, /* Line number. */ 592254225Speter char **pp, /* Pointer store. */ 593254225Speter size_t *lenp) /* Length store. */ 594254225Speter{ 595254225Speter DBT data, key; 596254225Speter EXF *ep; 597254225Speter 598254225Speter /* Check for no underlying file. */ 599254225Speter if ((ep = sp->ep) == NULL) 600254225Speter return (1); 601254225Speter 602254225Speter /* Get the line from the underlying database. */ 603254225Speter key.data = &lno; 604254225Speter key.size = sizeof(lno); 605254225Speter if (ep->db->get(ep->db, &key, &data, 0)) 606254225Speter /* We do not report error, and do not ensure the size! */ 607254225Speter return (1); 608254225Speter 609254225Speter if (lenp != NULL) 610254225Speter *lenp = data.size; 611254225Speter if (pp != NULL) 612254225Speter *pp = data.data; 613254225Speter return (0); 614254225Speter} 615254225Speter 616254225Speter/* 617254225Speter * db_rset -- 618254225Speter * Store a line in the file. No log, no conversion. 619254225Speter * 620254225Speter * PUBLIC: int db_rset __P((SCR *, recno_t, char *, size_t)); 621254225Speter */ 622254225Speterint 623254225Speterdb_rset( 624254225Speter SCR *sp, 625254225Speter recno_t lno, 626254225Speter char *p, 627254225Speter size_t len) 628254225Speter{ 629254225Speter DBT data, key; 630254225Speter EXF *ep; 631254225Speter 632254225Speter /* Check for no underlying file. */ 633254225Speter if ((ep = sp->ep) == NULL) 634254225Speter return (1); 635254225Speter 636254225Speter /* Update file. */ 637254225Speter key.data = &lno; 638254225Speter key.size = sizeof(lno); 639254225Speter data.data = p; 640254225Speter data.size = len; 641254225Speter if (ep->db->put(ep->db, &key, &data, 0) == -1) 642254225Speter /* We do not report error, and do not ensure the size! */ 643254225Speter return (1); 644254225Speter 645254225Speter return (0); 646254225Speter} 647254225Speter 648254225Speter/* 64919304Speter * db_err -- 65019304Speter * Report a line error. 65119304Speter * 65219304Speter * PUBLIC: void db_err __P((SCR *, recno_t)); 65319304Speter */ 65419304Spetervoid 655254225Speterdb_err( 656254225Speter SCR *sp, 657254225Speter recno_t lno) 65819304Speter{ 65919304Speter msgq(sp, M_ERR, 66019304Speter "008|Error: unable to retrieve line %lu", (u_long)lno); 66119304Speter} 66219304Speter 66319304Speter/* 66419304Speter * scr_update -- 66519304Speter * Update all of the screens that are backed by the file that 66619304Speter * just changed. 66719304Speter */ 66819304Speterstatic int 669254225Speterscr_update( 670254225Speter SCR *sp, 671254225Speter recno_t lno, 672254225Speter lnop_t op, 673254225Speter int current) 67419304Speter{ 67519304Speter EXF *ep; 67619304Speter SCR *tsp; 67719304Speter 67819304Speter if (F_ISSET(sp, SC_EX)) 67919304Speter return (0); 68019304Speter 68119304Speter ep = sp->ep; 68219304Speter if (ep->refcnt != 1) 683254225Speter TAILQ_FOREACH(tsp, sp->gp->dq, q) 68419304Speter if (sp != tsp && tsp->ep == ep) 68519304Speter if (vs_change(tsp, lno, op)) 68619304Speter return (1); 68719304Speter return (current ? vs_change(sp, lno, op) : 0); 68819304Speter} 689