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>
19 #include "gtxtextobj.h" /*Interface for this module */
20 #include "gtxwindows.h" /*Gator window interface */
21 #include "gtxcurseswin.h" /*Gator curses window interface */
22 #include "gtxdumbwin.h" /*Gator dumb terminal window interface */
23 #include "gtxX11win.h" /*Gator X11 window interface */
24 #include <stdio.h> /*Standard I/O stuff */
29 /*Externally-advertised array of text onode operations*/
30 struct onodeops gator_text_ops = {
36 static char mn[] = "gator_textobject"; /*Module name */
38 #define GATOR_TEXTCB_DO_BOX 0
40 /*------------------------------------------------------------------------
44 * Create a gator text object.
47 * struct onode *text_onp : Ptr to the text onode to fill out.
48 * struct onode_createparams *params : Generic ptr to creation
53 * Error value otherwise.
56 * The base onode fields have already been set. Text onodes are
57 * empty upon creation.
60 * Upon successful creation, the onode's o_window field is
61 * replaced with a new window created for the text object,
62 * with the parent window is remembered within the new window
63 * structure. On failure, it remains unchanged.
64 *------------------------------------------------------------------------*/
67 gator_text_create(struct onode *text_onp, struct onode_createparams *params)
68 { /*gator_text_create */
70 static char rn[] = "gator_text_create"; /*Routine name */
71 struct gator_textobj_params *text_params; /*My specific creation params */
72 struct gator_textobj *text_data; /*Ptr to private data */
73 struct gator_textcb_hdr *newCB; /*Ptr to CB hdr */
75 text_params = (struct gator_textobj_params *)params;
78 "[%s:%s] Private data passed to text object at %p:\n", mn,
80 fprintf(stderr, "\tmaxEntries: %d, maxCharsPerEntry: %d\n",
81 text_params->maxEntries, text_params->maxCharsPerEntry);
85 * Allocate the private data area.
89 "[%s:%s] Allocating %lu bytes for text object private data region\n",
90 mn, rn, sizeof(struct gator_textobj));
91 text_data = (struct gator_textobj *)malloc(sizeof(struct gator_textobj));
92 if (text_data == (struct gator_textobj *)0) {
94 "[%s:%s] Can't allocate %lu bytes for text object private data region, errno is %d\n",
95 mn, rn, sizeof(struct gator_textobj), errno);
100 * Create the text circular buffer for this new object.
103 fprintf(stderr, "[%s:%s] Creating circular buffer, %dx%d chars\n", mn,
104 rn, text_params->maxEntries, text_params->maxCharsPerEntry);
106 gator_textcb_Create(text_params->maxEntries,
107 text_params->maxCharsPerEntry);
108 if (newCB == (struct gator_textcb_hdr *)0) {
109 fprintf(stderr, "[%s:%s] Can't create text object circular buffer\n",
116 * Now that we have the private structures allocated, set them up.
118 text_data->llrock = (int *)0;
119 text_data->numLines = text_onp->o_height;
120 text_data->cbHdr = newCB;
121 text_data->firstEntShown = 0;
122 text_data->lastEntShown = 0;
124 fprintf(stderr, "[%s:%s] Number of lines in window: %d: ", mn, rn,
125 text_data->numLines);
128 * Attach the text-specific private
129 * data to the generic onode and return the happy news.
131 text_onp->o_data = (int *)text_data;
134 } /*gator_text_create */
136 /*------------------------------------------------------------------------
140 * Destroy a gator text object.
143 * struct onode *onp : Ptr to the text onode to delete.
147 * Error value otherwise.
150 * Nothing interesting.
154 *------------------------------------------------------------------------*/
157 gator_text_destroy(struct onode *onp)
158 { /*gator_text_destroy */
161 * For now, this is a no-op.
165 } /*gator_text_destroy */
167 /*------------------------------------------------------------------------
171 * Display/redraw a gator text object.
174 * struct onode *onp: Ptr to the text onode to display.
178 * Error value otherwise.
181 * Nothing interesting.
185 *------------------------------------------------------------------------*/
188 gator_text_display(struct onode *onp)
189 { /*gator_text_display */
191 static char rn[] = "gator_text_display"; /*Routine name */
192 struct gator_textobj *text_data; /*Ptr to text obj data */
193 struct gator_textcb_hdr *cbHdr; /*Ptr to CB header */
194 struct gwin_strparams strparams; /*String-drawing params */
195 int currLine; /*Current line being updated */
196 int currLinesUsed; /*Num screen lines used */
197 int currIdx; /*Current line index */
198 int currEnt; /*Current entry being drawn */
199 struct gator_textcb_entry *curr_ent; /*Ptr to current entry */
202 fprintf(stderr, "[%s:%s] Displaying text object at %p\n", mn, rn,
204 text_data = (struct gator_textobj *)(onp->o_data);
205 cbHdr = text_data->cbHdr;
208 "[%s:%s] Displaying text object at %p, object-specific data at %p\n",
209 mn, rn, onp, text_data);
212 * Update each line in the screen buffer with its proper contents.
214 currEnt = text_data->firstEntShown;
215 currLinesUsed = text_data->lastEntShown - currEnt + 1;
217 (cbHdr->oldestEntIdx +
218 (currEnt - cbHdr->oldestEnt)) % cbHdr->maxEntriesStored;
219 curr_ent = cbHdr->entry + currIdx;
223 "[%s:%s] Drawing %d populated lines, starting with entry %d (index %d) at %p",
224 mn, rn, currLinesUsed, currEnt, currIdx, curr_ent);
226 strparams.x = onp->o_x;
227 strparams.y = onp->o_y;
228 for (currLine = 0; currLine < text_data->numLines; currLine++) {
230 * Draw the current entry.
232 if (currLinesUsed > 0) {
234 * Drawing a populated line. We need to iterate if there are
235 * inversions (I don't feel like doing this now).
237 strparams.s = curr_ent->textp;
238 strparams.highlight = curr_ent->highlight;
239 WOP_DRAWSTRING(onp->o_window, &strparams);
244 if (currIdx >= cbHdr->maxEntriesStored) {
246 curr_ent = cbHdr->entry;
253 strparams.s = cbHdr->blankLine;
254 strparams.highlight = 0;
255 WOP_DRAWSTRING(onp->o_window, &strparams);
259 * Adjust the X and Y locations.
267 * Box the window before we leave.
269 #if GATOR_TEXTCB_DO_BOX
271 fprintf(stderr, "[%s:%s] Boxing window structure at 0x%x\n", mn, rn,
273 WOP_BOX(onp->o_window);
274 #endif /* GATOR_TEXTCB_DO_BOX */
277 * For now, this is all we do.
281 } /*gator_text_display */
283 /*------------------------------------------------------------------------
287 * Drop the refcount on a gator text object.
290 * struct onode *onp : Ptr to the onode whose refcount is
295 * Error value otherwise.
298 * Nothing interesting.
302 *------------------------------------------------------------------------*/
305 gator_text_release(struct onode *onp)
306 { /*gator_text_release */
309 * For now, this is a no-op.
313 } /*gator_text_release */
315 /*------------------------------------------------------------------------
319 * Scroll a text object some number of lines.
322 * struct onode *onp : Ptr to the text onode to be scrolled.
323 * int nlines : Number of lines to scroll.
324 * int direction : Scroll up or down?
328 * Error value otherwise.
331 * Invariant: the text object's firstEntShown and lastEntShown
332 * are always between oldestEnt and currEnt (inclusive).
336 *------------------------------------------------------------------------*/
339 gator_text_Scroll(struct onode *onp, int nlines, int direction)
340 { /*gator_text_Scroll */
342 static char rn[] = "gator_text_Scroll"; /*Routine name */
343 struct gator_textobj *text_data; /*Ptr to text obj data */
346 * We move the markers for first & last entries displayed, depending
347 * on what's available to us in the circular buffer. We never leave
351 fprintf(stderr, "[%s:%s] Scrolling text object %d lines %s\n",
353 (direction == GATOR_TEXT_SCROLL_UP) ? "UP" : "DOWN");
355 text_data = (struct gator_textobj *)(onp->o_data);
356 if (direction == GATOR_TEXT_SCROLL_DOWN) {
358 * Move the object's text ``down'' by sliding the window up.
360 text_data->firstEntShown -= nlines;
361 if (text_data->firstEntShown < text_data->cbHdr->oldestEnt)
362 text_data->firstEntShown = text_data->cbHdr->oldestEnt;
364 text_data->lastEntShown -= nlines;
365 if (text_data->lastEntShown < text_data->cbHdr->oldestEnt)
366 text_data->lastEntShown = text_data->cbHdr->oldestEnt;
371 * Move the object's text ``up'' by sliding the window down.
373 text_data->firstEntShown += nlines;
374 if (text_data->firstEntShown > text_data->cbHdr->currEnt)
375 text_data->firstEntShown = text_data->cbHdr->currEnt;
377 text_data->lastEntShown += nlines;
378 if (text_data->lastEntShown > text_data->cbHdr->currEnt)
379 text_data->lastEntShown = text_data->cbHdr->currEnt;
384 * Return the happy news.
388 } /*gator_text_Scroll */
390 /*------------------------------------------------------------------------
394 * Write the given string to the end of the gator text object.
397 * struct onode *onp : Ptr to the onode whose to which we're
399 * char *strToWrite : String to write.
400 * int numChars : Number of chars to write.
401 * int highlight : Use highlighting?
402 * int skip : Force a skip to the next line?
406 * Error value otherwise.
409 * Nothing interesting.
413 *------------------------------------------------------------------------*/
416 gator_text_Write(struct onode *onp, char *strToWrite, int numChars,
417 int highlight, int skip)
418 { /*gator_text_Write */
420 static char rn[] = "gator_text_Write"; /*Routine name */
421 register int code; /*Return value on routines */
422 struct gator_textobj *text_data; /*Ptr to text obj data */
423 struct gator_textcb_hdr *cbHdr; /*Ptr to text CB header */
424 int i; /*Loop variable */
425 int oldCurrEnt; /*CB's old currEnt value */
426 int redisplay; /*Redisplay after write? */
427 int shownDiff; /*Diff between 1st & last lines */
428 int writeDiff; /*Num lines really written */
429 int bumpAmount; /*Amount to bump count */
436 "[%s:%s] Writing %d chars to text object at %p (highlight=%d, skip=%d: '",
437 mn, rn, numChars, onp, highlight, skip);
438 for (i = 0; i < numChars; i++)
439 fprintf(stderr, "%c", strToWrite + i);
440 fprintf(stderr, "\n");
444 numChars = strlen(strToWrite); /* simplify caller */
445 text_data = (struct gator_textobj *)(onp->o_data);
446 cbHdr = text_data->cbHdr;
447 if (cbHdr == (struct gator_textcb_hdr *)0) {
448 fprintf(stderr, "[%s:%s] Text object missing its circular buffer!\n",
453 * If the current CB entry is being displayed, we track the write
454 * visually and redisplay.
456 if ((cbHdr->currEnt <= text_data->lastEntShown)
457 && (cbHdr->currEnt >= text_data->firstEntShown)) {
460 "[%s:%s] Current entry is on screen. Tracking this write\n",
462 oldCurrEnt = cbHdr->currEnt;
467 "[%s:%s] Current entry NOT on screen, not tracking write\n",
475 * We're tracking the write. Compute the number of screen lines
476 * actually written and adjust our own numbers, then call the
479 shownDiff = text_data->lastEntShown - text_data->firstEntShown;
480 writeDiff = cbHdr->currEnt - oldCurrEnt;
483 "[%s:%s] Preparing to redisplay. Difference in shown lines=%d, difference in written lines=%d\n",
484 mn, rn, shownDiff, writeDiff);
485 if (shownDiff < (text_data->numLines - 1)) {
487 * We weren't showing a full screen of stuff. Bump the last
488 * line shown by the minimum of the number of free lines still
489 * on the screen and the number of new lines actually written.
491 bumpAmount = (text_data->numLines - 1) - shownDiff;
492 if (writeDiff < bumpAmount)
493 bumpAmount = writeDiff;
494 text_data->lastEntShown += bumpAmount;
495 writeDiff -= bumpAmount;
498 "[%s:%s] Empty lines appeared on screen, bumping bottom line shown by %d; new writeDiff is %d\n",
499 mn, rn, bumpAmount, writeDiff);
503 * If we have any more lines that were written not taken care
504 * of by the above, we just bump the counters.
509 "[%s:%s] Still more lines need to be tracked. Moving first & last shown down by %d\n",
511 text_data->firstEntShown += writeDiff;
512 text_data->lastEntShown += writeDiff;
516 /*Redisplay needed */
518 * Simply call the circular buffer write op.
520 code = gator_textcb_Write(cbHdr, strToWrite, numChars, highlight, skip);
523 "[%s:%s] Can't write to text object's circular buffer, errror code is %d\n",
529 * Everything went well. Return the happy news.
533 } /*gator_text_Write */
535 /*------------------------------------------------------------------------
536 * gator_text_BlankLine
539 * Write a given number of blank lines to the given text object.
542 * struct onode *onp : Ptr to the onode to which we're writing.
543 * int numBlanks : Number of blank lines to write.
547 * Error value otherwise.
550 * Nothing interesting.
554 *------------------------------------------------------------------------*/
557 gator_text_BlankLine(struct onode *onp, int numBlanks)
558 { /*gator_text_BlankLine */
560 static char rn[] = "gator_text_BlankLine"; /*Routine name */
561 register int code; /*Return value on routines */
562 struct gator_textobj *text_data; /*Ptr to text obj data */
565 * We just call the circular buffer routine directly.
569 "[%s:%s] Writing %d blank lines to text object at %p\n", mn,
572 text_data = (struct gator_textobj *)(onp->o_data);
573 code = gator_textcb_BlankLine(text_data->cbHdr, numBlanks);
576 "[%s:%s] Can't write %d blank lines to text object at %p\n",
577 mn, rn, numBlanks, onp);
582 * Blank lines written successfully. Adjust what lines are currently
583 * shown. Iff we were tracking the end of the buffer, we have to
584 * follow the blank lines.
586 if (text_data->lastEntShown == text_data->cbHdr->currEnt - numBlanks) {
587 text_data->firstEntShown += numBlanks;
588 text_data->lastEntShown += numBlanks;
592 * Return the happy news.
596 } /*gator_text_BlankLine */