2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
12 * Implementation of the gator text object.
13 *------------------------------------------------------------------------*/
15 #include <afsconfig.h>
16 #include <afs/param.h>
21 #include "gtxtextobj.h" /*Interface for this module */
22 #include "gtxwindows.h" /*Gator window interface */
23 #include "gtxcurseswin.h" /*Gator curses window interface */
24 #include "gtxdumbwin.h" /*Gator dumb terminal window interface */
25 #include "gtxX11win.h" /*Gator X11 window interface */
26 #include <stdio.h> /*Standard I/O stuff */
38 /*Externally-advertised array of text onode operations*/
39 struct onodeops gator_text_ops = {
45 static char mn[] = "gator_textobject"; /*Module name */
47 #define GATOR_TEXTCB_DO_BOX 0
49 /*------------------------------------------------------------------------
53 * Create a gator text object.
56 * struct onode *text_onp : Ptr to the text onode to fill out.
57 * struct onode_createparams *params : Generic ptr to creation
62 * Error value otherwise.
65 * The base onode fields have already been set. Text onodes are
66 * empty upon creation.
69 * Upon successful creation, the onode's o_window field is
70 * replaced with a new window created for the text object,
71 * with the parent window is remembered within the new window
72 * structure. On failure, it remains unchanged.
73 *------------------------------------------------------------------------*/
76 gator_text_create(text_onp, params)
77 struct onode *text_onp;
78 struct onode_createparams *params;
80 { /*gator_text_create */
82 static char rn[] = "gator_text_create"; /*Routine name */
83 struct gator_textobj_params *text_params; /*My specific creation params */
84 struct gator_textobj *text_data; /*Ptr to private data */
85 struct gator_textcb_hdr *newCB; /*Ptr to CB hdr */
87 text_params = (struct gator_textobj_params *)params;
90 "[%s:%s] Private data passed to text object at 0x%x:\n", mn,
92 fprintf(stderr, "\tmaxEntries: %d, maxCharsPerEntry: %d\n",
93 text_params->maxEntries, text_params->maxCharsPerEntry);
97 * Allocate the private data area.
101 "[%s:%s] Allocating %d bytes for text object private data region\n",
102 mn, rn, sizeof(struct gator_textobj));
103 text_data = (struct gator_textobj *)malloc(sizeof(struct gator_textobj));
104 if (text_data == (struct gator_textobj *)0) {
106 "[%s:%s] Can't allocate %d bytes for text object private data region, errno is %d\n",
107 mn, rn, sizeof(struct gator_textobj), errno);
112 * Create the text circular buffer for this new object.
115 fprintf(stderr, "[%s:%s] Creating circular buffer, %dx%d chars\n", mn,
116 rn, text_params->maxEntries, text_params->maxCharsPerEntry);
118 gator_textcb_Create(text_params->maxEntries,
119 text_params->maxCharsPerEntry);
120 if (newCB == (struct gator_textcb_hdr *)0) {
121 fprintf(stderr, "[%s:%s] Can't create text object circular buffer\n",
128 * Now that we have the private structures allocated, set them up.
130 text_data->llrock = (int *)0;
131 text_data->numLines = text_onp->o_height;
132 text_data->cbHdr = newCB;
133 text_data->firstEntShown = 0;
134 text_data->lastEntShown = 0;
136 fprintf(stderr, "[%s:%s] Number of lines in window: %d: ", mn, rn,
137 text_data->numLines);
140 * Attach the text-specific private
141 * data to the generic onode and return the happy news.
143 text_onp->o_data = (int *)text_data;
146 } /*gator_text_create */
148 /*------------------------------------------------------------------------
152 * Destroy a gator text object.
155 * struct onode *onp : Ptr to the text onode to delete.
159 * Error value otherwise.
162 * Nothing interesting.
166 *------------------------------------------------------------------------*/
169 gator_text_destroy(onp)
172 { /*gator_text_destroy */
175 * For now, this is a no-op.
179 } /*gator_text_destroy */
181 /*------------------------------------------------------------------------
185 * Display/redraw a gator text object.
188 * struct onode *onp: Ptr to the text onode to display.
192 * Error value otherwise.
195 * Nothing interesting.
199 *------------------------------------------------------------------------*/
202 gator_text_display(onp)
205 { /*gator_text_display */
207 static char rn[] = "gator_text_display"; /*Routine name */
208 struct gator_textobj *text_data; /*Ptr to text obj data */
209 struct gator_textcb_hdr *cbHdr; /*Ptr to CB header */
210 struct gwin_strparams strparams; /*String-drawing params */
211 int currLine; /*Current line being updated */
212 int currLinesUsed; /*Num screen lines used */
213 int currIdx; /*Current line index */
214 int currEnt; /*Current entry being drawn */
215 struct gator_textcb_entry *curr_ent; /*Ptr to current entry */
218 fprintf(stderr, "[%s:%s] Displaying text object at 0x%x\n", mn, rn,
220 text_data = (struct gator_textobj *)(onp->o_data);
221 cbHdr = text_data->cbHdr;
224 "[%s:%s] Displaying text object at 0x%x, object-specific data at 0x%x\n",
225 mn, rn, onp, text_data);
228 * Update each line in the screen buffer with its proper contents.
230 currEnt = text_data->firstEntShown;
231 currLinesUsed = text_data->lastEntShown - currEnt + 1;
233 (cbHdr->oldestEntIdx +
234 (currEnt - cbHdr->oldestEnt)) % cbHdr->maxEntriesStored;
235 curr_ent = cbHdr->entry + currIdx;
239 "[%s:%s] Drawing %d populated lines, starting with entry %d (index %d) at 0x%x\n",
240 mn, rn, currLinesUsed, currEnt, currIdx, curr_ent);
242 strparams.x = onp->o_x;
243 strparams.y = onp->o_y;
244 for (currLine = 0; currLine < text_data->numLines; currLine++) {
246 * Draw the current entry.
248 if (currLinesUsed > 0) {
250 * Drawing a populated line. We need to iterate if there are
251 * inversions (I don't feel like doing this now).
253 strparams.s = curr_ent->textp;
254 strparams.highlight = curr_ent->highlight;
255 WOP_DRAWSTRING(onp->o_window, &strparams);
260 if (currIdx >= cbHdr->maxEntriesStored) {
262 curr_ent = cbHdr->entry;
269 strparams.s = cbHdr->blankLine;
270 strparams.highlight = 0;
271 WOP_DRAWSTRING(onp->o_window, &strparams);
275 * Adjust the X and Y locations.
283 * Box the window before we leave.
285 #if GATOR_TEXTCB_DO_BOX
287 fprintf(stderr, "[%s:%s] Boxing window structure at 0x%x\n", mn, rn,
289 WOP_BOX(onp->o_window);
290 #endif /* GATOR_TEXTCB_DO_BOX */
293 * For now, this is all we do.
297 } /*gator_text_display */
299 /*------------------------------------------------------------------------
303 * Drop the refcount on a gator text object.
306 * struct onode *onp : Ptr to the onode whose refcount is
311 * Error value otherwise.
314 * Nothing interesting.
318 *------------------------------------------------------------------------*/
321 gator_text_release(onp)
324 { /*gator_text_release */
327 * For now, this is a no-op.
331 } /*gator_text_release */
333 /*------------------------------------------------------------------------
337 * Scroll a text object some number of lines.
340 * struct onode *onp : Ptr to the text onode to be scrolled.
341 * int nlines : Number of lines to scroll.
342 * int direction : Scroll up or down?
346 * Error value otherwise.
349 * Invariant: the text object's firstEntShown and lastEntShown
350 * are always between oldestEnt and currEnt (inclusive).
354 *------------------------------------------------------------------------*/
357 gator_text_Scroll(onp, nlines, direction)
362 { /*gator_text_Scroll */
364 static char rn[] = "gator_text_Scroll"; /*Routine name */
365 struct gator_textobj *text_data; /*Ptr to text obj data */
368 * We move the markers for first & last entries displayed, depending
369 * on what's available to us in the circular buffer. We never leave
373 fprintf(stderr, "[%s:%s] Scrolling text object at 0x%x %d lines %s\n",
375 (direction == GATOR_TEXT_SCROLL_UP) ? "UP" : "DOWN");
377 text_data = (struct gator_textobj *)(onp->o_data);
378 if (direction == GATOR_TEXT_SCROLL_DOWN) {
380 * Move the object's text ``down'' by sliding the window up.
382 text_data->firstEntShown -= nlines;
383 if (text_data->firstEntShown < text_data->cbHdr->oldestEnt)
384 text_data->firstEntShown = text_data->cbHdr->oldestEnt;
386 text_data->lastEntShown -= nlines;
387 if (text_data->lastEntShown < text_data->cbHdr->oldestEnt)
388 text_data->lastEntShown = text_data->cbHdr->oldestEnt;
393 * Move the object's text ``up'' by sliding the window down.
395 text_data->firstEntShown += nlines;
396 if (text_data->firstEntShown > text_data->cbHdr->currEnt)
397 text_data->firstEntShown = text_data->cbHdr->currEnt;
399 text_data->lastEntShown += nlines;
400 if (text_data->lastEntShown > text_data->cbHdr->currEnt)
401 text_data->lastEntShown = text_data->cbHdr->currEnt;
406 * Return the happy news.
410 } /*gator_text_Scroll */
412 /*------------------------------------------------------------------------
416 * Write the given string to the end of the gator text object.
419 * struct onode *onp : Ptr to the onode whose to which we're
421 * char *strToWrite : String to write.
422 * int numChars : Number of chars to write.
423 * int highlight : Use highlighting?
424 * int skip : Force a skip to the next line?
428 * Error value otherwise.
431 * Nothing interesting.
435 *------------------------------------------------------------------------*/
438 gator_text_Write(onp, strToWrite, numChars, highlight, skip)
445 { /*gator_text_Write */
447 static char rn[] = "gator_text_Write"; /*Routine name */
448 register int code; /*Return value on routines */
449 struct gator_textobj *text_data; /*Ptr to text obj data */
450 struct gator_textcb_hdr *cbHdr; /*Ptr to text CB header */
451 int i; /*Loop variable */
452 int oldCurrEnt; /*CB's old currEnt value */
453 int redisplay; /*Redisplay after write? */
454 int shownDiff; /*Diff between 1st & last lines */
455 int writeDiff; /*Num lines really written */
456 int bumpAmount; /*Amount to bump count */
463 "[%s:%s] Writing %d chars to text object at 0x%x (highlight=%d, skip=%d: '",
464 rn, numChars, onp, highlight, skip);
465 for (i = 0; i < numChars; i++)
466 fprintf(stderr, "%c", strToWrite + i);
467 fprintf(stderr, "\n");
471 numChars = strlen(strToWrite); /* simplify caller */
472 text_data = (struct gator_textobj *)(onp->o_data);
473 cbHdr = text_data->cbHdr;
474 if (cbHdr == (struct gator_textcb_hdr *)0) {
475 fprintf(stderr, "[%s:%s] Text object missing its circular buffer!\n",
480 * If the current CB entry is being displayed, we track the write
481 * visually and redisplay.
483 if ((cbHdr->currEnt <= text_data->lastEntShown)
484 && (cbHdr->currEnt >= text_data->firstEntShown)) {
487 "[%s:%s] Current entry is on screen. Tracking this write\n",
489 oldCurrEnt = cbHdr->currEnt;
494 "[%s:%s] Current entry NOT on screen, not tracking write\n",
502 * We're tracking the write. Compute the number of screen lines
503 * actually written and adjust our own numbers, then call the
506 shownDiff = text_data->lastEntShown - text_data->firstEntShown;
507 writeDiff = cbHdr->currEnt - oldCurrEnt;
510 "[%s:%s] Preparing to redisplay. Difference in shown lines=%d, difference in written lines=%d\n",
511 mn, rn, shownDiff, writeDiff);
512 if (shownDiff < (text_data->numLines - 1)) {
514 * We weren't showing a full screen of stuff. Bump the last
515 * line shown by the minimum of the number of free lines still
516 * on the screen and the number of new lines actually written.
518 bumpAmount = (text_data->numLines - 1) - shownDiff;
519 if (writeDiff < bumpAmount)
520 bumpAmount = writeDiff;
521 text_data->lastEntShown += bumpAmount;
522 writeDiff -= bumpAmount;
525 "[%s:%s] Empty lines appeared on screen, bumping bottom line shown by %d; new writeDiff is %d\n",
526 mn, rn, bumpAmount, writeDiff);
530 * If we have any more lines that were written not taken care
531 * of by the above, we just bump the counters.
536 "[%s:%s] Still more lines need to be tracked. Moving first & last shown down by %d\n",
538 text_data->firstEntShown += writeDiff;
539 text_data->lastEntShown += writeDiff;
543 /*Redisplay needed */
545 * Simply call the circular buffer write op.
547 code = gator_textcb_Write(cbHdr, strToWrite, numChars, highlight, skip);
550 "[%s:%s] Can't write to text object's circular buffer, errror code is %d\n",
556 * Everything went well. Return the happy news.
560 } /*gator_text_Write */
562 /*------------------------------------------------------------------------
563 * gator_text_BlankLine
566 * Write a given number of blank lines to the given text object.
569 * struct onode *onp : Ptr to the onode to which we're writing.
570 * int numBlanks : Number of blank lines to write.
574 * Error value otherwise.
577 * Nothing interesting.
581 *------------------------------------------------------------------------*/
584 gator_text_BlankLine(onp, numBlanks)
588 { /*gator_text_BlankLine */
590 static char rn[] = "gator_text_BlankLine"; /*Routine name */
591 register int code; /*Return value on routines */
592 struct gator_textobj *text_data; /*Ptr to text obj data */
595 * We just call the circular buffer routine directly.
599 "[%s:%s] Writing %d blank lines to text object at 0x%x\n", mn,
602 text_data = (struct gator_textobj *)(onp->o_data);
603 code = gator_textcb_BlankLine(text_data->cbHdr, numBlanks);
606 "[%s:%s] Can't write %d blank lines to text object at 0x%x\n",
607 mn, rn, numBlanks, onp);
612 * Blank lines written successfully. Adjust what lines are currently
613 * shown. Iff we were tracking the end of the buffer, we have to
614 * follow the blank lines.
616 if (text_data->lastEntShown == text_data->cbHdr->currEnt - numBlanks) {
617 text_data->firstEntShown += numBlanks;
618 text_data->lastEntShown += numBlanks;
622 * Return the happy news.
626 } /*gator_text_BlankLine */