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 *------------------------------------------------------------------------*/
14 #include <afsconfig.h>
15 #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 */
25 /*Externally-advertised array of text onode operations*/
26 struct onodeops gator_text_ops
= {
32 static char mn
[] = "gator_textobject"; /*Module name */
34 #define GATOR_TEXTCB_DO_BOX 0
36 /*------------------------------------------------------------------------
40 * Create a gator text object.
43 * struct onode *text_onp : Ptr to the text onode to fill out.
44 * struct onode_createparams *params : Generic ptr to creation
49 * Error value otherwise.
52 * The base onode fields have already been set. Text onodes are
53 * empty upon creation.
56 * Upon successful creation, the onode's o_window field is
57 * replaced with a new window created for the text object,
58 * with the parent window is remembered within the new window
59 * structure. On failure, it remains unchanged.
60 *------------------------------------------------------------------------*/
63 gator_text_create(struct onode
*text_onp
, struct onode_createparams
*params
)
64 { /*gator_text_create */
66 static char rn
[] = "gator_text_create"; /*Routine name */
67 struct gator_textobj_params
*text_params
; /*My specific creation params */
68 struct gator_textobj
*text_data
; /*Ptr to private data */
69 struct gator_textcb_hdr
*newCB
; /*Ptr to CB hdr */
71 text_params
= (struct gator_textobj_params
*)params
;
74 "[%s:%s] Private data passed to text object at %p:\n", mn
,
76 fprintf(stderr
, "\tmaxEntries: %d, maxCharsPerEntry: %d\n",
77 text_params
->maxEntries
, text_params
->maxCharsPerEntry
);
81 * Allocate the private data area.
85 "[%s:%s] Allocating %" AFS_SIZET_FMT
" bytes for text object private data region\n",
86 mn
, rn
, sizeof(struct gator_textobj
));
87 text_data
= malloc(sizeof(struct gator_textobj
));
88 if (text_data
== (struct gator_textobj
*)0) {
90 "[%s:%s] Can't allocate %" AFS_SIZET_FMT
" bytes for text object private data region, errno is %d\n",
91 mn
, rn
, sizeof(struct gator_textobj
), errno
);
96 * Create the text circular buffer for this new object.
99 fprintf(stderr
, "[%s:%s] Creating circular buffer, %dx%d chars\n", mn
,
100 rn
, text_params
->maxEntries
, text_params
->maxCharsPerEntry
);
102 gator_textcb_Create(text_params
->maxEntries
,
103 text_params
->maxCharsPerEntry
);
104 if (newCB
== (struct gator_textcb_hdr
*)0) {
105 fprintf(stderr
, "[%s:%s] Can't create text object circular buffer\n",
112 * Now that we have the private structures allocated, set them up.
114 text_data
->llrock
= (int *)0;
115 text_data
->numLines
= text_onp
->o_height
;
116 text_data
->cbHdr
= newCB
;
117 text_data
->firstEntShown
= 0;
118 text_data
->lastEntShown
= 0;
120 fprintf(stderr
, "[%s:%s] Number of lines in window: %d: ", mn
, rn
,
121 text_data
->numLines
);
124 * Attach the text-specific private
125 * data to the generic onode and return the happy news.
127 text_onp
->o_data
= (int *)text_data
;
130 } /*gator_text_create */
132 /*------------------------------------------------------------------------
136 * Destroy a gator text object.
139 * struct onode *onp : Ptr to the text onode to delete.
143 * Error value otherwise.
146 * Nothing interesting.
150 *------------------------------------------------------------------------*/
153 gator_text_destroy(struct onode
*onp
)
154 { /*gator_text_destroy */
157 * For now, this is a no-op.
161 } /*gator_text_destroy */
163 /*------------------------------------------------------------------------
167 * Display/redraw a gator text object.
170 * struct onode *onp: Ptr to the text onode to display.
174 * Error value otherwise.
177 * Nothing interesting.
181 *------------------------------------------------------------------------*/
184 gator_text_display(struct onode
*onp
)
185 { /*gator_text_display */
187 static char rn
[] = "gator_text_display"; /*Routine name */
188 struct gator_textobj
*text_data
; /*Ptr to text obj data */
189 struct gator_textcb_hdr
*cbHdr
; /*Ptr to CB header */
190 struct gwin_strparams strparams
; /*String-drawing params */
191 int currLine
; /*Current line being updated */
192 int currLinesUsed
; /*Num screen lines used */
193 int currIdx
; /*Current line index */
194 int currEnt
; /*Current entry being drawn */
195 struct gator_textcb_entry
*curr_ent
; /*Ptr to current entry */
198 fprintf(stderr
, "[%s:%s] Displaying text object at %p\n", mn
, rn
,
200 text_data
= (struct gator_textobj
*)(onp
->o_data
);
201 cbHdr
= text_data
->cbHdr
;
204 "[%s:%s] Displaying text object at %p, object-specific data at %p\n",
205 mn
, rn
, onp
, text_data
);
208 * Update each line in the screen buffer with its proper contents.
210 currEnt
= text_data
->firstEntShown
;
211 currLinesUsed
= text_data
->lastEntShown
- currEnt
+ 1;
213 (cbHdr
->oldestEntIdx
+
214 (currEnt
- cbHdr
->oldestEnt
)) % cbHdr
->maxEntriesStored
;
215 curr_ent
= cbHdr
->entry
+ currIdx
;
219 "[%s:%s] Drawing %d populated lines, starting with entry %d (index %d) at %p",
220 mn
, rn
, currLinesUsed
, currEnt
, currIdx
, curr_ent
);
222 strparams
.x
= onp
->o_x
;
223 strparams
.y
= onp
->o_y
;
224 for (currLine
= 0; currLine
< text_data
->numLines
; currLine
++) {
226 * Draw the current entry.
228 if (currLinesUsed
> 0) {
230 * Drawing a populated line. We need to iterate if there are
231 * inversions (I don't feel like doing this now).
233 strparams
.s
= curr_ent
->textp
;
234 strparams
.highlight
= curr_ent
->highlight
;
235 WOP_DRAWSTRING(onp
->o_window
, &strparams
);
240 if (currIdx
>= cbHdr
->maxEntriesStored
) {
242 curr_ent
= cbHdr
->entry
;
249 strparams
.s
= cbHdr
->blankLine
;
250 strparams
.highlight
= 0;
251 WOP_DRAWSTRING(onp
->o_window
, &strparams
);
255 * Adjust the X and Y locations.
263 * Box the window before we leave.
265 #if GATOR_TEXTCB_DO_BOX
267 fprintf(stderr
, "[%s:%s] Boxing window structure at 0x%x\n", mn
, rn
,
269 WOP_BOX(onp
->o_window
);
270 #endif /* GATOR_TEXTCB_DO_BOX */
273 * For now, this is all we do.
277 } /*gator_text_display */
279 /*------------------------------------------------------------------------
283 * Drop the refcount on a gator text object.
286 * struct onode *onp : Ptr to the onode whose refcount is
291 * Error value otherwise.
294 * Nothing interesting.
298 *------------------------------------------------------------------------*/
301 gator_text_release(struct onode
*onp
)
302 { /*gator_text_release */
305 * For now, this is a no-op.
309 } /*gator_text_release */
311 /*------------------------------------------------------------------------
315 * Scroll a text object some number of lines.
318 * struct onode *onp : Ptr to the text onode to be scrolled.
319 * int nlines : Number of lines to scroll.
320 * int direction : Scroll up or down?
324 * Error value otherwise.
327 * Invariant: the text object's firstEntShown and lastEntShown
328 * are always between oldestEnt and currEnt (inclusive).
332 *------------------------------------------------------------------------*/
335 gator_text_Scroll(struct onode
*onp
, int nlines
, int direction
)
336 { /*gator_text_Scroll */
338 static char rn
[] = "gator_text_Scroll"; /*Routine name */
339 struct gator_textobj
*text_data
; /*Ptr to text obj data */
342 * We move the markers for first & last entries displayed, depending
343 * on what's available to us in the circular buffer. We never leave
347 fprintf(stderr
, "[%s:%s] Scrolling text object %d lines %s\n",
349 (direction
== GATOR_TEXT_SCROLL_UP
) ? "UP" : "DOWN");
351 text_data
= (struct gator_textobj
*)(onp
->o_data
);
352 if (direction
== GATOR_TEXT_SCROLL_DOWN
) {
354 * Move the object's text ``down'' by sliding the window up.
356 text_data
->firstEntShown
-= nlines
;
357 if (text_data
->firstEntShown
< text_data
->cbHdr
->oldestEnt
)
358 text_data
->firstEntShown
= text_data
->cbHdr
->oldestEnt
;
360 text_data
->lastEntShown
-= nlines
;
361 if (text_data
->lastEntShown
< text_data
->cbHdr
->oldestEnt
)
362 text_data
->lastEntShown
= text_data
->cbHdr
->oldestEnt
;
367 * Move the object's text ``up'' by sliding the window down.
369 text_data
->firstEntShown
+= nlines
;
370 if (text_data
->firstEntShown
> text_data
->cbHdr
->currEnt
)
371 text_data
->firstEntShown
= text_data
->cbHdr
->currEnt
;
373 text_data
->lastEntShown
+= nlines
;
374 if (text_data
->lastEntShown
> text_data
->cbHdr
->currEnt
)
375 text_data
->lastEntShown
= text_data
->cbHdr
->currEnt
;
380 * Return the happy news.
384 } /*gator_text_Scroll */
386 /*------------------------------------------------------------------------
390 * Write the given string to the end of the gator text object.
393 * struct onode *onp : Ptr to the onode whose to which we're
395 * char *strToWrite : String to write.
396 * int numChars : Number of chars to write.
397 * int highlight : Use highlighting?
398 * int skip : Force a skip to the next line?
402 * Error value otherwise.
405 * Nothing interesting.
409 *------------------------------------------------------------------------*/
412 gator_text_Write(struct onode
*onp
, char *strToWrite
, int numChars
,
413 int highlight
, int skip
)
414 { /*gator_text_Write */
416 static char rn
[] = "gator_text_Write"; /*Routine name */
417 int code
; /*Return value on routines */
418 struct gator_textobj
*text_data
; /*Ptr to text obj data */
419 struct gator_textcb_hdr
*cbHdr
; /*Ptr to text CB header */
420 int i
; /*Loop variable */
421 int oldCurrEnt
; /*CB's old currEnt value */
422 int redisplay
; /*Redisplay after write? */
423 int shownDiff
; /*Diff between 1st & last lines */
424 int writeDiff
; /*Num lines really written */
425 int bumpAmount
; /*Amount to bump count */
432 "[%s:%s] Writing %d chars to text object at %p (highlight=%d, skip=%d: '",
433 mn
, rn
, numChars
, onp
, highlight
, skip
);
434 for (i
= 0; i
< numChars
; i
++)
435 fprintf(stderr
, "%c", strToWrite
[i
]);
436 fprintf(stderr
, "\n");
440 numChars
= strlen(strToWrite
); /* simplify caller */
441 text_data
= (struct gator_textobj
*)(onp
->o_data
);
442 cbHdr
= text_data
->cbHdr
;
443 if (cbHdr
== (struct gator_textcb_hdr
*)0) {
444 fprintf(stderr
, "[%s:%s] Text object missing its circular buffer!\n",
449 * If the current CB entry is being displayed, we track the write
450 * visually and redisplay.
452 if ((cbHdr
->currEnt
<= text_data
->lastEntShown
)
453 && (cbHdr
->currEnt
>= text_data
->firstEntShown
)) {
456 "[%s:%s] Current entry is on screen. Tracking this write\n",
458 oldCurrEnt
= cbHdr
->currEnt
;
463 "[%s:%s] Current entry NOT on screen, not tracking write\n",
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
;
479 "[%s:%s] Preparing to redisplay. Difference in shown lines=%d, difference in written lines=%d\n",
480 mn
, rn
, shownDiff
, writeDiff
);
481 if (shownDiff
< (text_data
->numLines
- 1)) {
483 * We weren't showing a full screen of stuff. Bump the last
484 * line shown by the minimum of the number of free lines still
485 * on the screen and the number of new lines actually written.
487 bumpAmount
= (text_data
->numLines
- 1) - shownDiff
;
488 if (writeDiff
< bumpAmount
)
489 bumpAmount
= writeDiff
;
490 text_data
->lastEntShown
+= bumpAmount
;
491 writeDiff
-= bumpAmount
;
494 "[%s:%s] Empty lines appeared on screen, bumping bottom line shown by %d; new writeDiff is %d\n",
495 mn
, rn
, bumpAmount
, writeDiff
);
499 * If we have any more lines that were written not taken care
500 * of by the above, we just bump the counters.
505 "[%s:%s] Still more lines need to be tracked. Moving first & last shown down by %d\n",
507 text_data
->firstEntShown
+= writeDiff
;
508 text_data
->lastEntShown
+= writeDiff
;
512 /*Redisplay needed */
514 * Simply call the circular buffer write op.
516 code
= gator_textcb_Write(cbHdr
, strToWrite
, numChars
, highlight
, skip
);
519 "[%s:%s] Can't write to text object's circular buffer, errror code is %d\n",
525 * Everything went well. Return the happy news.
529 } /*gator_text_Write */
531 /*------------------------------------------------------------------------
532 * gator_text_BlankLine
535 * Write a given number of blank lines to the given text object.
538 * struct onode *onp : Ptr to the onode to which we're writing.
539 * int numBlanks : Number of blank lines to write.
543 * Error value otherwise.
546 * Nothing interesting.
550 *------------------------------------------------------------------------*/
553 gator_text_BlankLine(struct onode
*onp
, int numBlanks
)
554 { /*gator_text_BlankLine */
556 static char rn
[] = "gator_text_BlankLine"; /*Routine name */
557 int code
; /*Return value on routines */
558 struct gator_textobj
*text_data
; /*Ptr to text obj data */
561 * We just call the circular buffer routine directly.
565 "[%s:%s] Writing %d blank lines to text object at %p\n", mn
,
568 text_data
= (struct gator_textobj
*)(onp
->o_data
);
569 code
= gator_textcb_BlankLine(text_data
->cbHdr
, numBlanks
);
572 "[%s:%s] Can't write %d blank lines to text object at %p\n",
573 mn
, rn
, numBlanks
, onp
);
578 * Blank lines written successfully. Adjust what lines are currently
579 * shown. Iff we were tracking the end of the buffer, we have to
580 * follow the blank lines.
582 if (text_data
->lastEntShown
== text_data
->cbHdr
->currEnt
- numBlanks
) {
583 text_data
->firstEntShown
+= numBlanks
;
584 text_data
->lastEntShown
+= numBlanks
;
588 * Return the happy news.
592 } /*gator_text_BlankLine */