/* === wtbuf.c -- Back scroll buffer handler for WT === */ #ifdef __TURBOC__ #include #else #include #endif #include #include #include #include #include "wt.h" #include "wtbuf.h" #include "wtwin.h" /*=================*/ /*===== Types =====*/ /*=================*/ #define BLOCK_DATA 4000 typedef struct s_buf_block { struct s_buf_block far *prev_blk; struct s_buf_block far *next_blk; char far *last_lin; word blk_avail; byte far_mem; char blk_data[BLOCK_DATA]; } t_buf_block; #define BLOCK_SIZE sizeof(t_buf_block) #define LINE_HDR 2 #define PREV_LEN(p) ((byte) p[0]) #define THIS_LEN(p) ((byte) p[1]) #define DATA_TXT(p) (p+LINE_HDR) /*=====================*/ /*===== Variables =====*/ /*=====================*/ static t_buf_block far *blk_head = NULL; static t_buf_block far *blk_tail = NULL; static t_buf_block far *blk_curr = NULL; static t_buf_block far *blk_disp = NULL; static char far *lin_disp = NULL; /* This temp buffer is for the current (line) data. */ /* It stores data until a CR, then the line gets */ /* copied into the big buffer. */ static char tmp_buf[160], *tmp_ptr; static word tmp_count; extern int back_visible = 0; static int buf_wdoheight; /*============================*/ /*===== Local Prototypes =====*/ /*============================*/ void farncpy(void const far *src, void far *dst, size_t n); /*===========================*/ /*===== Local Functions =====*/ /*===========================*/ void block_clear(t_buf_block far *blk) { blk->last_lin = NULL; blk->blk_avail = BLOCK_DATA; } /* end block_clear() */ /******************************************/ /* buf_ins(): insert new text into buffer */ /******************************************/ void buf_ins(void) { byte prvlen; if (blk_head == NULL) return; /* If space not available, free current head buffer */ if (blk_tail->blk_avail < tmp_count + LINE_HDR + 10) { blk_tail = blk_tail->next_blk; if (blk_tail == blk_head) { /* wrapped around? */ blk_head = blk_head->next_blk; if (blk_disp == blk_tail) { /* move disp ptr out of danger */ blk_disp = blk_head; lin_disp = blk_disp->blk_data; } block_clear(blk_tail); } } /* Write a new line into current block */ if (blk_tail->last_lin == NULL) { prvlen = 0; blk_tail->last_lin = blk_tail->blk_data; } else { prvlen = THIS_LEN(blk_tail->last_lin); blk_tail->last_lin += LINE_HDR + prvlen; } PREV_LEN(blk_tail->last_lin) = prvlen; THIS_LEN(blk_tail->last_lin) = tmp_count; farncpy(tmp_buf, DATA_TXT(blk_tail->last_lin), tmp_count); blk_tail->blk_avail -= tmp_count + LINE_HDR; /* --- clear tmp buffer for new data --- */ tmp_count = 0; tmp_ptr = tmp_buf; } /* end buf_ins() */ /****************************************************/ /* farncpy(): Copy from one far location to another */ /****************************************************/ void farncpy(void const far *src, void far *dst, size_t n) { for ( ; n; n--) { *((byte far *) dst) = *((byte far *) src); dst = ((byte far *) dst) + 1; src = ((byte far *) src) + 1; } } /* END farncpy() */ /*============================*/ /*===== Global functions =====*/ /*============================*/ /***********************************************************/ /* buf_backswitch(): turn background display on/off/toggle */ /***********************************************************/ int buf_backswitch(int func) { win_select(WIN_BACK); if (back_visible) { if (func == -1 || func == 0) { win_hide(); back_visible = 0; } } else if (!back_visible) { if (func == -1 || func == 1) { win_show(); back_visible = 1; } } return back_visible; } /* end buf_backswitch() */ /*********************************************************/ /* buf_display(): display buffer, starting with blk_disp */ /*********************************************************/ void buf_display(void) { t_buf_block far *bp; char far *lp; int j; if (blk_head == NULL) return; win_select(WIN_BACK); win_clear(); for (j=1,bp=blk_disp,lp=lin_disp; ; j++) { farncpy(DATA_TXT(lp), tmp_buf, THIS_LEN(lp)); tmp_buf[THIS_LEN(lp)] = '\0'; win_puts(tmp_buf); if (j == buf_wdoheight) break; win_puts("\r\n"); if (lp == blk_tail->last_lin) break; if (lp == bp->last_lin) { bp = bp->next_blk; lp = bp->blk_data; } else { lp += THIS_LEN(lp) + LINE_HDR; } } } /* end buf_display() */ /*******************************************/ /* buf_init(): Initialize buffer structure */ /* */ /* The buffer consists of several 8KB */ /* buffer blocks chained to one another. */ /* Within a block are strucures of type */ /* buf_line. */ /*******************************************/ word buf_init(void) { void far *reserve; word buffer_count = 0; t_buf_block *near_blk; blk_head = NULL; blk_tail = NULL; blk_curr = NULL; blk_disp = NULL; lin_disp = NULL; /* Allocate the first 2 buffers in near memory. */ /* This creates a minimal buffer even without far memory. */ near_blk = (t_buf_block *) calloc(1, BLOCK_SIZE); if (near_blk == NULL) goto no_buf; (t_buf_block huge *) blk_head = near_blk; block_clear(blk_head); blk_head->far_mem = 0; near_blk = (t_buf_block *) calloc(1, BLOCK_SIZE); if (near_blk == NULL) goto no_buf; (t_buf_block huge *) blk_tail = near_blk; block_clear(blk_tail); blk_tail->far_mem = 0; blk_head->prev_blk = blk_tail; blk_head->next_blk = blk_tail; blk_tail->prev_blk = blk_head; blk_tail->next_blk = blk_head; buffer_count = 2; /* now try to allocate more blocks in far memory. */ reserve = farcalloc(1L, 20000L); if (reserve != NULL) { for (;;) { (t_buf_block huge *) blk_curr = (t_buf_block far *) farcalloc(1L, BLOCK_SIZE); if (blk_curr == NULL) break; block_clear(blk_curr); blk_curr->far_mem = 1; blk_head->prev_blk = blk_curr; blk_curr->next_blk = blk_head; blk_curr->prev_blk = blk_tail; blk_tail->next_blk = blk_curr; blk_tail = blk_curr; buffer_count++; } /* end for */ farfree(reserve); } blk_tail = blk_head; blk_disp = blk_head; lin_disp = blk_disp->blk_data; sprintf(tmp_buf, "\r\nScroll buffer size: %ld bytes.", buffer_count * (unsigned long) BLOCK_DATA); display(tmp_buf, 1); finish: back_visible = 0; tmp_ptr = tmp_buf; tmp_count = 0; return buffer_count; no_buf: win_select(WIN_MAIN); win_puts("No memory available for back scroll buffer!\n"); goto finish; } /* end buf_init() */ /*************************************************/ /* buf_position(): set/move buffer start pointer */ /*************************************************/ void buf_position(int func) { int j; if (blk_head == NULL) return; switch (func) { case POS_FIRST: blk_disp = blk_head; lin_disp = blk_disp->blk_data; break; case POS_PGUP: for (j=0; jblk_data) { if (lin_disp == blk_disp->blk_data) { blk_disp = blk_disp->prev_blk; lin_disp = blk_disp->last_lin; } else { lin_disp -= (PREV_LEN(lin_disp) + LINE_HDR); } } break; case POS_NEXT: if (lin_disp != blk_tail->last_lin) { if (lin_disp == blk_disp->last_lin) { blk_disp = blk_disp->next_blk; lin_disp = blk_disp->blk_data; } else { lin_disp += THIS_LEN(lin_disp) + LINE_HDR; } } break; case POS_PGDN: for (j=0; jlast_lin; buf_position(POS_PGUP); break; } /* end switch() */ } /* end buf_position() */ /************************************************/ /* buf_setheight(): Set height of buffer window */ /************************************************/ void buf_setheight(int height) { buf_wdoheight = height; } /* end buf_setheight() */ /*******************************************/ /* buf_term(): release back scroll buffers */ /*******************************************/ void buf_term(void) { if (blk_head == NULL) return; /* break buffer chain */ assert(blk_head->prev_blk != NULL); assert(blk_head->prev_blk->next_blk == blk_head); blk_head->prev_blk->next_blk = NULL; /* release chain, starting at head */ do { blk_curr = blk_head->next_blk; if (blk_head->far_mem) { farfree(blk_head); } else { free((t_buf_block *) blk_head); } blk_head = blk_curr; } while (blk_head != NULL); blk_head = NULL; blk_tail = NULL; blk_disp = NULL; } /* end buf_term() */ /********************************************/ /* buf_write(): Write data into temp buffer */ /********************************************/ void buf_write(char *txt, int cr) { int l; l = strlen(txt); if (l + tmp_count >= sizeof(tmp_buf)) { buf_ins(); } strcpy(tmp_ptr, txt); tmp_count += l; tmp_ptr += l; if (cr) { buf_ins(); } } /* end buf_write() */ /* EOF(WtBuf.C) */