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>
20 #include "gtxtextobj.h" /*Interface for this module*/
21 #include "gtxwindows.h" /*Gator window interface*/
22 #include "gtxcurseswin.h" /*Gator curses window interface*/
23 #include "gtxdumbwin.h" /*Gator dumb terminal window interface*/
24 #include "gtxX11win.h" /*Gator X11 window interface*/
25 #include <stdio.h> /*Standard I/O stuff*/
37 /*Externally-advertised array of text onode operations*/
38 struct onodeops gator_text_ops = {
44 static char mn[] = "gator_textobject"; /*Module name*/
46 #define GATOR_TEXTCB_DO_BOX 0
48 /*------------------------------------------------------------------------
52 * Create a gator text object.
55 * struct onode *text_onp : Ptr to the text onode to fill out.
56 * struct onode_createparams *params : Generic ptr to creation
61 * Error value otherwise.
64 * The base onode fields have already been set. Text onodes are
65 * empty upon creation.
68 * Upon successful creation, the onode's o_window field is
69 * replaced with a new window created for the text object,
70 * with the parent window is remembered within the new window
71 * structure. On failure, it remains unchanged.
72 *------------------------------------------------------------------------*/
74 int gator_text_create(text_onp, params)
75 struct onode *text_onp;
76 struct onode_createparams *params;
78 { /*gator_text_create*/
80 static char rn[] = "gator_text_create"; /*Routine name*/
81 struct gator_textobj_params *text_params; /*My specific creation params*/
82 struct gator_textobj *text_data; /*Ptr to private data*/
83 struct gator_textcb_hdr *newCB; /*Ptr to CB hdr*/
85 text_params = (struct gator_textobj_params *)params;
87 fprintf(stderr, "[%s:%s] Private data passed to text object at 0x%x:\n", mn, rn, text_onp);
88 fprintf(stderr, "\tmaxEntries: %d, maxCharsPerEntry: %d\n",
89 text_params->maxEntries, text_params->maxCharsPerEntry);
93 * Allocate the private data area.
96 fprintf(stderr, "[%s:%s] Allocating %d bytes for text object private data region\n", mn, rn, sizeof(struct gator_textobj));
97 text_data = (struct gator_textobj *) malloc(sizeof(struct gator_textobj));
98 if (text_data == (struct gator_textobj *)0) {
99 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);
104 * Create the text circular buffer for this new object.
107 fprintf(stderr, "[%s:%s] Creating circular buffer, %dx%d chars\n", mn, rn, text_params->maxEntries, text_params->maxCharsPerEntry);
108 newCB = gator_textcb_Create(text_params->maxEntries,
109 text_params->maxCharsPerEntry);
110 if (newCB == (struct gator_textcb_hdr *)0) {
111 fprintf(stderr, "[%s:%s] Can't create text object circular buffer\n", mn, rn);
117 * Now that we have the private structures allocated, set them up.
119 text_data->llrock = (int *)0;
120 text_data->numLines = text_onp->o_height;
121 text_data->cbHdr = newCB;
122 text_data->firstEntShown = 0;
123 text_data->lastEntShown = 0;
125 fprintf(stderr, "[%s:%s] Number of lines in window: %d: ", mn, rn, 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 *------------------------------------------------------------------------*/
156 int gator_text_destroy(onp)
159 { /*gator_text_destroy*/
162 * For now, this is a no-op.
166 } /*gator_text_destroy*/
168 /*------------------------------------------------------------------------
172 * Display/redraw a gator text object.
175 * struct onode *onp: Ptr to the text onode to display.
179 * Error value otherwise.
182 * Nothing interesting.
186 *------------------------------------------------------------------------*/
188 int gator_text_display(onp)
191 { /*gator_text_display*/
193 static char rn[] = "gator_text_display"; /*Routine name*/
194 struct gator_textobj *text_data; /*Ptr to text obj data*/
195 struct gator_textcb_hdr *cbHdr; /*Ptr to CB header*/
196 struct gwin_strparams strparams; /*String-drawing params*/
197 int currLine; /*Current line being updated*/
198 int currLinesUsed; /*Num screen lines used*/
199 int currIdx; /*Current line index*/
200 int currEnt; /*Current entry being drawn*/
201 struct gator_textcb_entry *curr_ent; /*Ptr to current entry*/
204 fprintf(stderr, "[%s:%s] Displaying text object at 0x%x\n", mn, rn, onp);
205 text_data = (struct gator_textobj *)(onp->o_data);
206 cbHdr = text_data->cbHdr;
208 fprintf(stderr, "[%s:%s] Displaying text object at 0x%x, object-specific data at 0x%x\n", mn, rn, onp, text_data);
211 * Update each line in the screen buffer with its proper contents.
213 currEnt = text_data->firstEntShown;
214 currLinesUsed = text_data->lastEntShown - currEnt + 1;
215 currIdx = (cbHdr->oldestEntIdx + (currEnt - cbHdr->oldestEnt)) % cbHdr->maxEntriesStored;
216 curr_ent = cbHdr->entry + currIdx;
219 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);
221 strparams.x = onp->o_x;
222 strparams.y = onp->o_y;
223 for (currLine = 0; currLine < text_data->numLines; currLine++) {
225 * Draw the current entry.
227 if (currLinesUsed > 0) {
229 * Drawing a populated line. We need to iterate if there are
230 * inversions (I don't feel like doing this now).
232 strparams.s = curr_ent->textp;
233 strparams.highlight = curr_ent->highlight;
234 WOP_DRAWSTRING(onp->o_window, &strparams);
239 if (currIdx >= cbHdr->maxEntriesStored) {
241 curr_ent = cbHdr->entry;
250 strparams.s = cbHdr->blankLine;
251 strparams.highlight = 0;
252 WOP_DRAWSTRING(onp->o_window, &strparams);
256 * Adjust the X and Y locations.
264 * Box the window before we leave.
266 #if GATOR_TEXTCB_DO_BOX
268 fprintf(stderr, "[%s:%s] Boxing window structure at 0x%x\n",
269 mn, rn, onp->o_window);
270 WOP_BOX(onp->o_window);
271 #endif /* GATOR_TEXTCB_DO_BOX */
274 * For now, this is all we do.
278 } /*gator_text_display*/
280 /*------------------------------------------------------------------------
284 * Drop the refcount on a gator text object.
287 * struct onode *onp : Ptr to the onode whose refcount is
292 * Error value otherwise.
295 * Nothing interesting.
299 *------------------------------------------------------------------------*/
301 int gator_text_release(onp)
304 { /*gator_text_release*/
307 * For now, this is a no-op.
311 } /*gator_text_release*/
313 /*------------------------------------------------------------------------
317 * Scroll a text object some number of lines.
320 * struct onode *onp : Ptr to the text onode to be scrolled.
321 * int nlines : Number of lines to scroll.
322 * int direction : Scroll up or down?
326 * Error value otherwise.
329 * Invariant: the text object's firstEntShown and lastEntShown
330 * are always between oldestEnt and currEnt (inclusive).
334 *------------------------------------------------------------------------*/
336 int gator_text_Scroll(onp, nlines, direction)
341 { /*gator_text_Scroll*/
343 static char rn[] = "gator_text_Scroll"; /*Routine name*/
344 struct gator_textobj *text_data; /*Ptr to text obj data*/
347 * We move the markers for first & last entries displayed, depending
348 * on what's available to us in the circular buffer. We never leave
352 fprintf(stderr, "[%s:%s] Scrolling text object at 0x%x %d lines %s\n", mn, rn, nlines, (direction == GATOR_TEXT_SCROLL_UP) ? "UP" : "DOWN");
354 text_data = (struct gator_textobj *)(onp->o_data);
355 if (direction == GATOR_TEXT_SCROLL_DOWN) {
357 * Move the object's text ``down'' by sliding the window up.
359 text_data->firstEntShown -= nlines;
360 if (text_data->firstEntShown < text_data->cbHdr->oldestEnt)
361 text_data->firstEntShown = text_data->cbHdr->oldestEnt;
363 text_data->lastEntShown -= nlines;
364 if (text_data->lastEntShown < text_data->cbHdr->oldestEnt)
365 text_data->lastEntShown = text_data->cbHdr->oldestEnt;
370 * Move the object's text ``up'' by sliding the window down.
372 text_data->firstEntShown += nlines;
373 if (text_data->firstEntShown > text_data->cbHdr->currEnt)
374 text_data->firstEntShown = text_data->cbHdr->currEnt;
376 text_data->lastEntShown += nlines;
377 if (text_data->lastEntShown > text_data->cbHdr->currEnt)
378 text_data->lastEntShown = text_data->cbHdr->currEnt;
383 * Return the happy news.
387 } /*gator_text_Scroll*/
389 /*------------------------------------------------------------------------
393 * Write the given string to the end of the gator text object.
396 * struct onode *onp : Ptr to the onode whose to which we're
398 * char *strToWrite : String to write.
399 * int numChars : Number of chars to write.
400 * int highlight : Use highlighting?
401 * int skip : Force a skip to the next line?
405 * Error value otherwise.
408 * Nothing interesting.
412 *------------------------------------------------------------------------*/
414 int gator_text_Write(onp, strToWrite, numChars, highlight, skip)
421 { /*gator_text_Write*/
423 static char rn[] = "gator_text_Write"; /*Routine name*/
424 register int code; /*Return value on routines*/
425 struct gator_textobj *text_data; /*Ptr to text obj data*/
426 struct gator_textcb_hdr *cbHdr; /*Ptr to text CB header*/
427 int i; /*Loop variable*/
428 int oldCurrEnt; /*CB's old currEnt value*/
429 int redisplay; /*Redisplay after write?*/
430 int shownDiff; /*Diff between 1st & last lines*/
431 int writeDiff; /*Num lines really written*/
432 int bumpAmount; /*Amount to bump count*/
438 fprintf(stderr, "[%s:%s] Writing %d chars to text object at 0x%x (highlight=%d, skip=%d: '", rn, numChars, onp, highlight, skip);
439 for (i=0; i < numChars; i++)
440 fprintf(stderr, "%c", strToWrite+i);
441 fprintf(stderr, "\n");
444 if (numChars == 0) 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", mn, rn);
452 * If the current CB entry is being displayed, we track the write
453 * visually and redisplay.
455 if ((cbHdr->currEnt <= text_data->lastEntShown) &&
456 (cbHdr->currEnt >= text_data->firstEntShown)) {
458 fprintf(stderr, "[%s:%s] Current entry is on screen. Tracking this write\n", mn, rn);
459 oldCurrEnt = cbHdr->currEnt;
464 fprintf(stderr, "[%s:%s] Current entry NOT on screen, not tracking write\n", mn, rn);
471 * We're tracking the write. Compute the number of screen lines
472 * actually written and adjust our own numbers, then call the
475 shownDiff = text_data->lastEntShown - text_data->firstEntShown;
476 writeDiff = cbHdr->currEnt - oldCurrEnt;
478 fprintf(stderr, "[%s:%s] Preparing to redisplay. Difference in shown lines=%d, difference in written lines=%d\n", mn, rn, shownDiff, writeDiff);
479 if (shownDiff < (text_data->numLines - 1)) {
481 * We weren't showing a full screen of stuff. Bump the last
482 * line shown by the minimum of the number of free lines still
483 * on the screen and the number of new lines actually written.
485 bumpAmount = (text_data->numLines - 1) - shownDiff;
486 if (writeDiff < bumpAmount)
487 bumpAmount = writeDiff;
488 text_data->lastEntShown += bumpAmount;
489 writeDiff -= bumpAmount;
491 fprintf(stderr, "[%s:%s] Empty lines appeared on screen, bumping bottom line shown by %d; new writeDiff is %d\n", mn, rn, bumpAmount, writeDiff);
495 * If we have any more lines that were written not taken care
496 * of by the above, we just bump the counters.
500 fprintf(stderr, "[%s:%s] Still more lines need to be tracked. Moving first & last shown down by %d\n", mn, rn, writeDiff);
501 text_data->firstEntShown += writeDiff;
502 text_data->lastEntShown += writeDiff;
504 } /*Redisplay needed*/
507 * Simply call the circular buffer write op.
509 code = gator_textcb_Write(cbHdr, strToWrite, numChars, highlight, skip);
511 fprintf(stderr, "[%s:%s] Can't write to text object's circular buffer, errror code is %d\n", mn, rn, code);
516 * Everything went well. Return the happy news.
520 } /*gator_text_Write*/
522 /*------------------------------------------------------------------------
523 * gator_text_BlankLine
526 * Write a given number of blank lines to the given text object.
529 * struct onode *onp : Ptr to the onode to which we're writing.
530 * int numBlanks : Number of blank lines to write.
534 * Error value otherwise.
537 * Nothing interesting.
541 *------------------------------------------------------------------------*/
543 int gator_text_BlankLine(onp, numBlanks)
547 { /*gator_text_BlankLine*/
549 static char rn[] = "gator_text_BlankLine"; /*Routine name*/
550 register int code; /*Return value on routines*/
551 struct gator_textobj *text_data; /*Ptr to text obj data*/
554 * We just call the circular buffer routine directly.
557 fprintf(stderr, "[%s:%s] Writing %d blank lines to text object at 0x%x\n", mn, rn, numBlanks, onp);
559 text_data = (struct gator_textobj *)(onp->o_data);
560 code = gator_textcb_BlankLine(text_data->cbHdr, numBlanks);
562 fprintf(stderr, "[%s:%s] Can't write %d blank lines to text object at 0x%x\n", mn, rn, numBlanks, onp);
567 * Blank lines written successfully. Adjust what lines are currently
568 * shown. Iff we were tracking the end of the buffer, we have to
569 * follow the blank lines.
571 if (text_data->lastEntShown == text_data->cbHdr->currEnt - numBlanks) {
572 text_data->firstEntShown += numBlanks;
573 text_data->lastEntShown += numBlanks;
577 * Return the happy news.
581 } /*gator_text_BlankLine*/