openafs/src/gtx/textobject.c
Derrick Brashear 872bc94f8c reindent-20030715
FIXES 1774

thanks to nneul@umr.edu for providing a script to do this.
gnu indent 2.2.9 options:
-npro -nbad -bap -nbc -bbo -br -ce -cdw -brs -ncdb -cp1 -ncs -di2 -ndj -nfc1
-nfca -i4 -lp -npcs -nprs -psl -sc -nsob -ts8

====================
This delta was composed from multiple commits as part of the CVS->Git migration.
The checkin message with each commit was inconsistent.
The following are the additional commit messages.
====================
FIXES 1774

fix subst mistake
2003-07-16 00:28:24 +00:00

627 lines
17 KiB
C

/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
*
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
*/
/*
* Description:
* Implementation of the gator text object.
*------------------------------------------------------------------------*/
#define IGNORE_STDS_H
#include <afsconfig.h>
#include <afs/param.h>
RCSID
("$Header$");
#include "gtxtextobj.h" /*Interface for this module */
#include "gtxwindows.h" /*Gator window interface */
#include "gtxcurseswin.h" /*Gator curses window interface */
#include "gtxdumbwin.h" /*Gator dumb terminal window interface */
#include "gtxX11win.h" /*Gator X11 window interface */
#include <stdio.h> /*Standard I/O stuff */
#include <errno.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include <stdlib.h>
/*Externally-advertised array of text onode operations*/
struct onodeops gator_text_ops = {
gator_text_destroy,
gator_text_display,
gator_text_release
};
static char mn[] = "gator_textobject"; /*Module name */
#define GATOR_TEXTCB_DO_BOX 0
/*------------------------------------------------------------------------
* gator_text_create
*
* Description:
* Create a gator text object.
*
* Arguments:
* struct onode *text_onp : Ptr to the text onode to fill out.
* struct onode_createparams *params : Generic ptr to creation
* parameters.
*
* Returns:
* Zero if successful,
* Error value otherwise.
*
* Environment:
* The base onode fields have already been set. Text onodes are
* empty upon creation.
*
* Side Effects:
* Upon successful creation, the onode's o_window field is
* replaced with a new window created for the text object,
* with the parent window is remembered within the new window
* structure. On failure, it remains unchanged.
*------------------------------------------------------------------------*/
int
gator_text_create(text_onp, params)
struct onode *text_onp;
struct onode_createparams *params;
{ /*gator_text_create */
static char rn[] = "gator_text_create"; /*Routine name */
struct gator_textobj_params *text_params; /*My specific creation params */
struct gator_textobj *text_data; /*Ptr to private data */
struct gator_textcb_hdr *newCB; /*Ptr to CB hdr */
text_params = (struct gator_textobj_params *)params;
if (objects_debug) {
fprintf(stderr,
"[%s:%s] Private data passed to text object at 0x%x:\n", mn,
rn, text_onp);
fprintf(stderr, "\tmaxEntries: %d, maxCharsPerEntry: %d\n",
text_params->maxEntries, text_params->maxCharsPerEntry);
}
/*
* Allocate the private data area.
*/
if (objects_debug)
fprintf(stderr,
"[%s:%s] Allocating %d bytes for text object private data region\n",
mn, rn, sizeof(struct gator_textobj));
text_data = (struct gator_textobj *)malloc(sizeof(struct gator_textobj));
if (text_data == (struct gator_textobj *)0) {
fprintf(stderr,
"[%s:%s] Can't allocate %d bytes for text object private data region, errno is %d\n",
mn, rn, sizeof(struct gator_textobj), errno);
return (errno);
}
/*
* Create the text circular buffer for this new object.
*/
if (objects_debug)
fprintf(stderr, "[%s:%s] Creating circular buffer, %dx%d chars\n", mn,
rn, text_params->maxEntries, text_params->maxCharsPerEntry);
newCB =
gator_textcb_Create(text_params->maxEntries,
text_params->maxCharsPerEntry);
if (newCB == (struct gator_textcb_hdr *)0) {
fprintf(stderr, "[%s:%s] Can't create text object circular buffer\n",
mn, rn);
free(text_data);
return (-1);
}
/*
* Now that we have the private structures allocated, set them up.
*/
text_data->llrock = (int *)0;
text_data->numLines = text_onp->o_height;
text_data->cbHdr = newCB;
text_data->firstEntShown = 0;
text_data->lastEntShown = 0;
if (objects_debug)
fprintf(stderr, "[%s:%s] Number of lines in window: %d: ", mn, rn,
text_data->numLines);
/*
* Attach the text-specific private
* data to the generic onode and return the happy news.
*/
text_onp->o_data = (int *)text_data;
return (0);
} /*gator_text_create */
/*------------------------------------------------------------------------
* gator_text_destroy
*
* Description:
* Destroy a gator text object.
*
* Arguments:
* struct onode *onp : Ptr to the text onode to delete.
*
* Returns:
* 0: Success
* Error value otherwise.
*
* Environment:
* Nothing interesting.
*
* Side Effects:
* As advertised.
*------------------------------------------------------------------------*/
int
gator_text_destroy(onp)
struct onode *onp;
{ /*gator_text_destroy */
/*
* For now, this is a no-op.
*/
return (0);
} /*gator_text_destroy */
/*------------------------------------------------------------------------
* gator_text_display
*
* Description:
* Display/redraw a gator text object.
*
* Arguments:
* struct onode *onp: Ptr to the text onode to display.
*
* Returns:
* 0: Success
* Error value otherwise.
*
* Environment:
* Nothing interesting.
*
* Side Effects:
* As advertised.
*------------------------------------------------------------------------*/
int
gator_text_display(onp)
struct onode *onp;
{ /*gator_text_display */
static char rn[] = "gator_text_display"; /*Routine name */
struct gator_textobj *text_data; /*Ptr to text obj data */
struct gator_textcb_hdr *cbHdr; /*Ptr to CB header */
struct gwin_strparams strparams; /*String-drawing params */
int currLine; /*Current line being updated */
int currLinesUsed; /*Num screen lines used */
int currIdx; /*Current line index */
int currEnt; /*Current entry being drawn */
struct gator_textcb_entry *curr_ent; /*Ptr to current entry */
if (objects_debug)
fprintf(stderr, "[%s:%s] Displaying text object at 0x%x\n", mn, rn,
onp);
text_data = (struct gator_textobj *)(onp->o_data);
cbHdr = text_data->cbHdr;
if (objects_debug)
fprintf(stderr,
"[%s:%s] Displaying text object at 0x%x, object-specific data at 0x%x\n",
mn, rn, onp, text_data);
/*
* Update each line in the screen buffer with its proper contents.
*/
currEnt = text_data->firstEntShown;
currLinesUsed = text_data->lastEntShown - currEnt + 1;
currIdx =
(cbHdr->oldestEntIdx +
(currEnt - cbHdr->oldestEnt)) % cbHdr->maxEntriesStored;
curr_ent = cbHdr->entry + currIdx;
if (objects_debug)
fprintf(stderr,
"[%s:%s] Drawing %d populated lines, starting with entry %d (index %d) at 0x%x\n",
mn, rn, currLinesUsed, currEnt, currIdx, curr_ent);
strparams.x = onp->o_x;
strparams.y = onp->o_y;
for (currLine = 0; currLine < text_data->numLines; currLine++) {
/*
* Draw the current entry.
*/
if (currLinesUsed > 0) {
/*
* Drawing a populated line. We need to iterate if there are
* inversions (I don't feel like doing this now).
*/
strparams.s = curr_ent->textp;
strparams.highlight = curr_ent->highlight;
WOP_DRAWSTRING(onp->o_window, &strparams);
currLinesUsed--;
currEnt++;
currIdx++;
if (currIdx >= cbHdr->maxEntriesStored) {
currIdx = 0;
curr_ent = cbHdr->entry;
} else
curr_ent++;
} else {
/*
* Draw a blank line.
*/
strparams.s = cbHdr->blankLine;
strparams.highlight = 0;
WOP_DRAWSTRING(onp->o_window, &strparams);
}
/*
* Adjust the X and Y locations.
*/
strparams.x = 0;
strparams.y++;
} /*Update loop */
/*
* Box the window before we leave.
*/
#if GATOR_TEXTCB_DO_BOX
if (objects_debug)
fprintf(stderr, "[%s:%s] Boxing window structure at 0x%x\n", mn, rn,
onp->o_window);
WOP_BOX(onp->o_window);
#endif /* GATOR_TEXTCB_DO_BOX */
/*
* For now, this is all we do.
*/
return (0);
} /*gator_text_display */
/*------------------------------------------------------------------------
* gator_text_release
*
* Description:
* Drop the refcount on a gator text object.
*
* Arguments:
* struct onode *onp : Ptr to the onode whose refcount is
* to be dropped.
*
* Returns:
* 0: Success
* Error value otherwise.
*
* Environment:
* Nothing interesting.
*
* Side Effects:
* As advertised.
*------------------------------------------------------------------------*/
int
gator_text_release(onp)
struct onode *onp;
{ /*gator_text_release */
/*
* For now, this is a no-op.
*/
return (0);
} /*gator_text_release */
/*------------------------------------------------------------------------
* gator_text_Scroll
*
* Description:
* Scroll a text object some number of lines.
*
* Arguments:
* struct onode *onp : Ptr to the text onode to be scrolled.
* int nlines : Number of lines to scroll.
* int direction : Scroll up or down?
*
* Returns:
* 0: Success,
* Error value otherwise.
*
* Environment:
* Invariant: the text object's firstEntShown and lastEntShown
* are always between oldestEnt and currEnt (inclusive).
*
* Side Effects:
* As advertised.
*------------------------------------------------------------------------*/
int
gator_text_Scroll(onp, nlines, direction)
struct onode *onp;
int nlines;
int direction;
{ /*gator_text_Scroll */
static char rn[] = "gator_text_Scroll"; /*Routine name */
struct gator_textobj *text_data; /*Ptr to text obj data */
/*
* We move the markers for first & last entries displayed, depending
* on what's available to us in the circular buffer. We never leave
* the window empty.
*/
if (objects_debug)
fprintf(stderr, "[%s:%s] Scrolling text object at 0x%x %d lines %s\n",
mn, rn, nlines,
(direction == GATOR_TEXT_SCROLL_UP) ? "UP" : "DOWN");
text_data = (struct gator_textobj *)(onp->o_data);
if (direction == GATOR_TEXT_SCROLL_DOWN) {
/*
* Move the object's text ``down'' by sliding the window up.
*/
text_data->firstEntShown -= nlines;
if (text_data->firstEntShown < text_data->cbHdr->oldestEnt)
text_data->firstEntShown = text_data->cbHdr->oldestEnt;
text_data->lastEntShown -= nlines;
if (text_data->lastEntShown < text_data->cbHdr->oldestEnt)
text_data->lastEntShown = text_data->cbHdr->oldestEnt;
} /*Moving down */
else {
/*
* Move the object's text ``up'' by sliding the window down.
*/
text_data->firstEntShown += nlines;
if (text_data->firstEntShown > text_data->cbHdr->currEnt)
text_data->firstEntShown = text_data->cbHdr->currEnt;
text_data->lastEntShown += nlines;
if (text_data->lastEntShown > text_data->cbHdr->currEnt)
text_data->lastEntShown = text_data->cbHdr->currEnt;
} /*Moving up */
/*
* Return the happy news.
*/
return (0);
} /*gator_text_Scroll */
/*------------------------------------------------------------------------
* gator_text_Write
*
* Description:
* Write the given string to the end of the gator text object.
*
* Arguments:
* struct onode *onp : Ptr to the onode whose to which we're
* writing.
* char *strToWrite : String to write.
* int numChars : Number of chars to write.
* int highlight : Use highlighting?
* int skip : Force a skip to the next line?
*
* Returns:
* 0: Success
* Error value otherwise.
*
* Environment:
* Nothing interesting.
*
* Side Effects:
* As advertised.
*------------------------------------------------------------------------*/
int
gator_text_Write(onp, strToWrite, numChars, highlight, skip)
struct onode *onp;
char *strToWrite;
int numChars;
int highlight;
int skip;
{ /*gator_text_Write */
static char rn[] = "gator_text_Write"; /*Routine name */
register int code; /*Return value on routines */
struct gator_textobj *text_data; /*Ptr to text obj data */
struct gator_textcb_hdr *cbHdr; /*Ptr to text CB header */
int i; /*Loop variable */
int oldCurrEnt; /*CB's old currEnt value */
int redisplay; /*Redisplay after write? */
int shownDiff; /*Diff between 1st & last lines */
int writeDiff; /*Num lines really written */
int bumpAmount; /*Amount to bump count */
/*
*
*/
if (objects_debug) {
fprintf(stderr,
"[%s:%s] Writing %d chars to text object at 0x%x (highlight=%d, skip=%d: '",
rn, numChars, onp, highlight, skip);
for (i = 0; i < numChars; i++)
fprintf(stderr, "%c", strToWrite + i);
fprintf(stderr, "\n");
}
if (numChars == 0)
numChars = strlen(strToWrite); /* simplify caller */
text_data = (struct gator_textobj *)(onp->o_data);
cbHdr = text_data->cbHdr;
if (cbHdr == (struct gator_textcb_hdr *)0) {
fprintf(stderr, "[%s:%s] Text object missing its circular buffer!\n",
mn, rn);
return (-1);
}
/*
* If the current CB entry is being displayed, we track the write
* visually and redisplay.
*/
if ((cbHdr->currEnt <= text_data->lastEntShown)
&& (cbHdr->currEnt >= text_data->firstEntShown)) {
if (objects_debug)
fprintf(stderr,
"[%s:%s] Current entry is on screen. Tracking this write\n",
mn, rn);
oldCurrEnt = cbHdr->currEnt;
redisplay = 1;
} else {
if (objects_debug)
fprintf(stderr,
"[%s:%s] Current entry NOT on screen, not tracking write\n",
mn, rn);
redisplay = 0;
}
if (redisplay) {
/*
* We're tracking the write. Compute the number of screen lines
* actually written and adjust our own numbers, then call the
* display function.
*/
shownDiff = text_data->lastEntShown - text_data->firstEntShown;
writeDiff = cbHdr->currEnt - oldCurrEnt;
if (objects_debug)
fprintf(stderr,
"[%s:%s] Preparing to redisplay. Difference in shown lines=%d, difference in written lines=%d\n",
mn, rn, shownDiff, writeDiff);
if (shownDiff < (text_data->numLines - 1)) {
/*
* We weren't showing a full screen of stuff. Bump the last
* line shown by the minimum of the number of free lines still
* on the screen and the number of new lines actually written.
*/
bumpAmount = (text_data->numLines - 1) - shownDiff;
if (writeDiff < bumpAmount)
bumpAmount = writeDiff;
text_data->lastEntShown += bumpAmount;
writeDiff -= bumpAmount;
if (objects_debug)
fprintf(stderr,
"[%s:%s] Empty lines appeared on screen, bumping bottom line shown by %d; new writeDiff is %d\n",
mn, rn, bumpAmount, writeDiff);
}
/*
* If we have any more lines that were written not taken care
* of by the above, we just bump the counters.
*/
if (writeDiff > 0) {
if (objects_debug)
fprintf(stderr,
"[%s:%s] Still more lines need to be tracked. Moving first & last shown down by %d\n",
mn, rn, writeDiff);
text_data->firstEntShown += writeDiff;
text_data->lastEntShown += writeDiff;
}
}
/*Redisplay needed */
/*
* Simply call the circular buffer write op.
*/
code = gator_textcb_Write(cbHdr, strToWrite, numChars, highlight, skip);
if (code) {
fprintf(stderr,
"[%s:%s] Can't write to text object's circular buffer, errror code is %d\n",
mn, rn, code);
return (code);
}
/*
* Everything went well. Return the happy news.
*/
return (0);
} /*gator_text_Write */
/*------------------------------------------------------------------------
* gator_text_BlankLine
*
* Description:
* Write a given number of blank lines to the given text object.
*
* Arguments:
* struct onode *onp : Ptr to the onode to which we're writing.
* int numBlanks : Number of blank lines to write.
*
* Returns:
* 0: Success,
* Error value otherwise.
*
* Environment:
* Nothing interesting.
*
* Side Effects:
* As advertised.
*------------------------------------------------------------------------*/
int
gator_text_BlankLine(onp, numBlanks)
struct onode *onp;
int numBlanks;
{ /*gator_text_BlankLine */
static char rn[] = "gator_text_BlankLine"; /*Routine name */
register int code; /*Return value on routines */
struct gator_textobj *text_data; /*Ptr to text obj data */
/*
* We just call the circular buffer routine directly.
*/
if (objects_debug)
fprintf(stderr,
"[%s:%s] Writing %d blank lines to text object at 0x%x\n", mn,
rn, numBlanks, onp);
text_data = (struct gator_textobj *)(onp->o_data);
code = gator_textcb_BlankLine(text_data->cbHdr, numBlanks);
if (code) {
fprintf(stderr,
"[%s:%s] Can't write %d blank lines to text object at 0x%x\n",
mn, rn, numBlanks, onp);
return (code);
}
/*
* Blank lines written successfully. Adjust what lines are currently
* shown. Iff we were tracking the end of the buffer, we have to
* follow the blank lines.
*/
if (text_data->lastEntShown == text_data->cbHdr->currEnt - numBlanks) {
text_data->firstEntShown += numBlanks;
text_data->lastEntShown += numBlanks;
}
/*
* Return the happy news.
*/
return (0);
} /*gator_text_BlankLine */