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 */
31 /*Externally-advertised array of text onode operations*/
32 struct onodeops gator_text_ops = {
38 static char mn[] = "gator_textobject"; /*Module name */
40 #define GATOR_TEXTCB_DO_BOX 0
42 /*------------------------------------------------------------------------
46 * Create a gator text object.
49 * struct onode *text_onp : Ptr to the text onode to fill out.
50 * struct onode_createparams *params : Generic ptr to creation
55 * Error value otherwise.
58 * The base onode fields have already been set. Text onodes are
59 * empty upon creation.
62 * Upon successful creation, the onode's o_window field is
63 * replaced with a new window created for the text object,
64 * with the parent window is remembered within the new window
65 * structure. On failure, it remains unchanged.
66 *------------------------------------------------------------------------*/
69 gator_text_create(text_onp, params)
70 struct onode *text_onp;
71 struct onode_createparams *params;
73 { /*gator_text_create */
75 static char rn[] = "gator_text_create"; /*Routine name */
76 struct gator_textobj_params *text_params; /*My specific creation params */
77 struct gator_textobj *text_data; /*Ptr to private data */
78 struct gator_textcb_hdr *newCB; /*Ptr to CB hdr */
80 text_params = (struct gator_textobj_params *)params;
83 "[%s:%s] Private data passed to text object at 0x%x:\n", mn,
85 fprintf(stderr, "\tmaxEntries: %d, maxCharsPerEntry: %d\n",
86 text_params->maxEntries, text_params->maxCharsPerEntry);
90 * Allocate the private data area.
94 "[%s:%s] Allocating %d bytes for text object private data region\n",
95 mn, rn, sizeof(struct gator_textobj));
96 text_data = (struct gator_textobj *)malloc(sizeof(struct gator_textobj));
97 if (text_data == (struct gator_textobj *)0) {
99 "[%s:%s] Can't allocate %d bytes for text object private data region, errno is %d\n",
100 mn, rn, sizeof(struct gator_textobj), errno);
105 * Create the text circular buffer for this new object.
108 fprintf(stderr, "[%s:%s] Creating circular buffer, %dx%d chars\n", mn,
109 rn, text_params->maxEntries, text_params->maxCharsPerEntry);
111 gator_textcb_Create(text_params->maxEntries,
112 text_params->maxCharsPerEntry);
113 if (newCB == (struct gator_textcb_hdr *)0) {
114 fprintf(stderr, "[%s:%s] Can't create text object circular buffer\n",
121 * Now that we have the private structures allocated, set them up.
123 text_data->llrock = (int *)0;
124 text_data->numLines = text_onp->o_height;
125 text_data->cbHdr = newCB;
126 text_data->firstEntShown = 0;
127 text_data->lastEntShown = 0;
129 fprintf(stderr, "[%s:%s] Number of lines in window: %d: ", mn, rn,
130 text_data->numLines);
133 * Attach the text-specific private
134 * data to the generic onode and return the happy news.
136 text_onp->o_data = (int *)text_data;
139 } /*gator_text_create */
141 /*------------------------------------------------------------------------
145 * Destroy a gator text object.
148 * struct onode *onp : Ptr to the text onode to delete.
152 * Error value otherwise.
155 * Nothing interesting.
159 *------------------------------------------------------------------------*/
162 gator_text_destroy(onp)
165 { /*gator_text_destroy */
168 * For now, this is a no-op.
172 } /*gator_text_destroy */
174 /*------------------------------------------------------------------------
178 * Display/redraw a gator text object.
181 * struct onode *onp: Ptr to the text onode to display.
185 * Error value otherwise.
188 * Nothing interesting.
192 *------------------------------------------------------------------------*/
195 gator_text_display(onp)
198 { /*gator_text_display */
200 static char rn[] = "gator_text_display"; /*Routine name */
201 struct gator_textobj *text_data; /*Ptr to text obj data */
202 struct gator_textcb_hdr *cbHdr; /*Ptr to CB header */
203 struct gwin_strparams strparams; /*String-drawing params */
204 int currLine; /*Current line being updated */
205 int currLinesUsed; /*Num screen lines used */
206 int currIdx; /*Current line index */
207 int currEnt; /*Current entry being drawn */
208 struct gator_textcb_entry *curr_ent; /*Ptr to current entry */
211 fprintf(stderr, "[%s:%s] Displaying text object at 0x%x\n", mn, rn,
213 text_data = (struct gator_textobj *)(onp->o_data);
214 cbHdr = text_data->cbHdr;
217 "[%s:%s] Displaying text object at 0x%x, object-specific data at 0x%x\n",
218 mn, rn, onp, text_data);
221 * Update each line in the screen buffer with its proper contents.
223 currEnt = text_data->firstEntShown;
224 currLinesUsed = text_data->lastEntShown - currEnt + 1;
226 (cbHdr->oldestEntIdx +
227 (currEnt - cbHdr->oldestEnt)) % cbHdr->maxEntriesStored;
228 curr_ent = cbHdr->entry + currIdx;
232 "[%s:%s] Drawing %d populated lines, starting with entry %d (index %d) at 0x%x\n",
233 mn, rn, currLinesUsed, currEnt, currIdx, curr_ent);
235 strparams.x = onp->o_x;
236 strparams.y = onp->o_y;
237 for (currLine = 0; currLine < text_data->numLines; currLine++) {
239 * Draw the current entry.
241 if (currLinesUsed > 0) {
243 * Drawing a populated line. We need to iterate if there are
244 * inversions (I don't feel like doing this now).
246 strparams.s = curr_ent->textp;
247 strparams.highlight = curr_ent->highlight;
248 WOP_DRAWSTRING(onp->o_window, &strparams);
253 if (currIdx >= cbHdr->maxEntriesStored) {
255 curr_ent = cbHdr->entry;
262 strparams.s = cbHdr->blankLine;
263 strparams.highlight = 0;
264 WOP_DRAWSTRING(onp->o_window, &strparams);
268 * Adjust the X and Y locations.
276 * Box the window before we leave.
278 #if GATOR_TEXTCB_DO_BOX
280 fprintf(stderr, "[%s:%s] Boxing window structure at 0x%x\n", mn, rn,
282 WOP_BOX(onp->o_window);
283 #endif /* GATOR_TEXTCB_DO_BOX */
286 * For now, this is all we do.
290 } /*gator_text_display */
292 /*------------------------------------------------------------------------
296 * Drop the refcount on a gator text object.
299 * struct onode *onp : Ptr to the onode whose refcount is
304 * Error value otherwise.
307 * Nothing interesting.
311 *------------------------------------------------------------------------*/
314 gator_text_release(onp)
317 { /*gator_text_release */
320 * For now, this is a no-op.
324 } /*gator_text_release */
326 /*------------------------------------------------------------------------
330 * Scroll a text object some number of lines.
333 * struct onode *onp : Ptr to the text onode to be scrolled.
334 * int nlines : Number of lines to scroll.
335 * int direction : Scroll up or down?
339 * Error value otherwise.
342 * Invariant: the text object's firstEntShown and lastEntShown
343 * are always between oldestEnt and currEnt (inclusive).
347 *------------------------------------------------------------------------*/
350 gator_text_Scroll(onp, nlines, direction)
355 { /*gator_text_Scroll */
357 static char rn[] = "gator_text_Scroll"; /*Routine name */
358 struct gator_textobj *text_data; /*Ptr to text obj data */
361 * We move the markers for first & last entries displayed, depending
362 * on what's available to us in the circular buffer. We never leave
366 fprintf(stderr, "[%s:%s] Scrolling text object at 0x%x %d lines %s\n",
368 (direction == GATOR_TEXT_SCROLL_UP) ? "UP" : "DOWN");
370 text_data = (struct gator_textobj *)(onp->o_data);
371 if (direction == GATOR_TEXT_SCROLL_DOWN) {
373 * Move the object's text ``down'' by sliding the window up.
375 text_data->firstEntShown -= nlines;
376 if (text_data->firstEntShown < text_data->cbHdr->oldestEnt)
377 text_data->firstEntShown = text_data->cbHdr->oldestEnt;
379 text_data->lastEntShown -= nlines;
380 if (text_data->lastEntShown < text_data->cbHdr->oldestEnt)
381 text_data->lastEntShown = text_data->cbHdr->oldestEnt;
386 * Move the object's text ``up'' by sliding the window down.
388 text_data->firstEntShown += nlines;
389 if (text_data->firstEntShown > text_data->cbHdr->currEnt)
390 text_data->firstEntShown = text_data->cbHdr->currEnt;
392 text_data->lastEntShown += nlines;
393 if (text_data->lastEntShown > text_data->cbHdr->currEnt)
394 text_data->lastEntShown = text_data->cbHdr->currEnt;
399 * Return the happy news.
403 } /*gator_text_Scroll */
405 /*------------------------------------------------------------------------
409 * Write the given string to the end of the gator text object.
412 * struct onode *onp : Ptr to the onode whose to which we're
414 * char *strToWrite : String to write.
415 * int numChars : Number of chars to write.
416 * int highlight : Use highlighting?
417 * int skip : Force a skip to the next line?
421 * Error value otherwise.
424 * Nothing interesting.
428 *------------------------------------------------------------------------*/
431 gator_text_Write(onp, strToWrite, numChars, highlight, skip)
438 { /*gator_text_Write */
440 static char rn[] = "gator_text_Write"; /*Routine name */
441 register int code; /*Return value on routines */
442 struct gator_textobj *text_data; /*Ptr to text obj data */
443 struct gator_textcb_hdr *cbHdr; /*Ptr to text CB header */
444 int i; /*Loop variable */
445 int oldCurrEnt; /*CB's old currEnt value */
446 int redisplay; /*Redisplay after write? */
447 int shownDiff; /*Diff between 1st & last lines */
448 int writeDiff; /*Num lines really written */
449 int bumpAmount; /*Amount to bump count */
456 "[%s:%s] Writing %d chars to text object at 0x%x (highlight=%d, skip=%d: '",
457 rn, numChars, onp, highlight, skip);
458 for (i = 0; i < numChars; i++)
459 fprintf(stderr, "%c", strToWrite + i);
460 fprintf(stderr, "\n");
464 numChars = strlen(strToWrite); /* simplify caller */
465 text_data = (struct gator_textobj *)(onp->o_data);
466 cbHdr = text_data->cbHdr;
467 if (cbHdr == (struct gator_textcb_hdr *)0) {
468 fprintf(stderr, "[%s:%s] Text object missing its circular buffer!\n",
473 * If the current CB entry is being displayed, we track the write
474 * visually and redisplay.
476 if ((cbHdr->currEnt <= text_data->lastEntShown)
477 && (cbHdr->currEnt >= text_data->firstEntShown)) {
480 "[%s:%s] Current entry is on screen. Tracking this write\n",
482 oldCurrEnt = cbHdr->currEnt;
487 "[%s:%s] Current entry NOT on screen, not tracking write\n",
495 * We're tracking the write. Compute the number of screen lines
496 * actually written and adjust our own numbers, then call the
499 shownDiff = text_data->lastEntShown - text_data->firstEntShown;
500 writeDiff = cbHdr->currEnt - oldCurrEnt;
503 "[%s:%s] Preparing to redisplay. Difference in shown lines=%d, difference in written lines=%d\n",
504 mn, rn, shownDiff, writeDiff);
505 if (shownDiff < (text_data->numLines - 1)) {
507 * We weren't showing a full screen of stuff. Bump the last
508 * line shown by the minimum of the number of free lines still
509 * on the screen and the number of new lines actually written.
511 bumpAmount = (text_data->numLines - 1) - shownDiff;
512 if (writeDiff < bumpAmount)
513 bumpAmount = writeDiff;
514 text_data->lastEntShown += bumpAmount;
515 writeDiff -= bumpAmount;
518 "[%s:%s] Empty lines appeared on screen, bumping bottom line shown by %d; new writeDiff is %d\n",
519 mn, rn, bumpAmount, writeDiff);
523 * If we have any more lines that were written not taken care
524 * of by the above, we just bump the counters.
529 "[%s:%s] Still more lines need to be tracked. Moving first & last shown down by %d\n",
531 text_data->firstEntShown += writeDiff;
532 text_data->lastEntShown += writeDiff;
536 /*Redisplay needed */
538 * Simply call the circular buffer write op.
540 code = gator_textcb_Write(cbHdr, strToWrite, numChars, highlight, skip);
543 "[%s:%s] Can't write to text object's circular buffer, errror code is %d\n",
549 * Everything went well. Return the happy news.
553 } /*gator_text_Write */
555 /*------------------------------------------------------------------------
556 * gator_text_BlankLine
559 * Write a given number of blank lines to the given text object.
562 * struct onode *onp : Ptr to the onode to which we're writing.
563 * int numBlanks : Number of blank lines to write.
567 * Error value otherwise.
570 * Nothing interesting.
574 *------------------------------------------------------------------------*/
577 gator_text_BlankLine(onp, numBlanks)
581 { /*gator_text_BlankLine */
583 static char rn[] = "gator_text_BlankLine"; /*Routine name */
584 register int code; /*Return value on routines */
585 struct gator_textobj *text_data; /*Ptr to text obj data */
588 * We just call the circular buffer routine directly.
592 "[%s:%s] Writing %d blank lines to text object at 0x%x\n", mn,
595 text_data = (struct gator_textobj *)(onp->o_data);
596 code = gator_textcb_BlankLine(text_data->cbHdr, numBlanks);
599 "[%s:%s] Can't write %d blank lines to text object at 0x%x\n",
600 mn, rn, numBlanks, onp);
605 * Blank lines written successfully. Adjust what lines are currently
606 * shown. Iff we were tracking the end of the buffer, we have to
607 * follow the blank lines.
609 if (text_data->lastEntShown == text_data->cbHdr->currEnt - numBlanks) {
610 text_data->firstEntShown += numBlanks;
611 text_data->lastEntShown += numBlanks;
615 * Return the happy news.
619 } /*gator_text_BlankLine */