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>
18 #include "gtxtextobj.h" /*Interface for this module */
19 #include "gtxwindows.h" /*Gator window interface */
20 #include "gtxcurseswin.h" /*Gator curses window interface */
21 #include "gtxdumbwin.h" /*Gator dumb terminal window interface */
22 #include "gtxX11win.h" /*Gator X11 window interface */
23 #include <stdio.h> /*Standard I/O stuff */
28 /*Externally-advertised array of text onode operations*/
29 struct onodeops gator_text_ops
= {
35 static char mn
[] = "gator_textobject"; /*Module name */
37 #define GATOR_TEXTCB_DO_BOX 0
39 /*------------------------------------------------------------------------
43 * Create a gator text object.
46 * struct onode *text_onp : Ptr to the text onode to fill out.
47 * struct onode_createparams *params : Generic ptr to creation
52 * Error value otherwise.
55 * The base onode fields have already been set. Text onodes are
56 * empty upon creation.
59 * Upon successful creation, the onode's o_window field is
60 * replaced with a new window created for the text object,
61 * with the parent window is remembered within the new window
62 * structure. On failure, it remains unchanged.
63 *------------------------------------------------------------------------*/
66 gator_text_create(struct onode
*text_onp
, struct onode_createparams
*params
)
67 { /*gator_text_create */
69 static char rn
[] = "gator_text_create"; /*Routine name */
70 struct gator_textobj_params
*text_params
; /*My specific creation params */
71 struct gator_textobj
*text_data
; /*Ptr to private data */
72 struct gator_textcb_hdr
*newCB
; /*Ptr to CB hdr */
74 text_params
= (struct gator_textobj_params
*)params
;
77 "[%s:%s] Private data passed to text object at %p:\n", mn
,
79 fprintf(stderr
, "\tmaxEntries: %d, maxCharsPerEntry: %d\n",
80 text_params
->maxEntries
, text_params
->maxCharsPerEntry
);
84 * Allocate the private data area.
88 "[%s:%s] Allocating %" AFS_SIZET_FMT
" bytes for text object private data region\n",
89 mn
, rn
, sizeof(struct gator_textobj
));
90 text_data
= (struct gator_textobj
*)malloc(sizeof(struct gator_textobj
));
91 if (text_data
== (struct gator_textobj
*)0) {
93 "[%s:%s] Can't allocate %" AFS_SIZET_FMT
" bytes for text object private data region, errno is %d\n",
94 mn
, rn
, sizeof(struct gator_textobj
), errno
);
99 * Create the text circular buffer for this new object.
102 fprintf(stderr
, "[%s:%s] Creating circular buffer, %dx%d chars\n", mn
,
103 rn
, text_params
->maxEntries
, text_params
->maxCharsPerEntry
);
105 gator_textcb_Create(text_params
->maxEntries
,
106 text_params
->maxCharsPerEntry
);
107 if (newCB
== (struct gator_textcb_hdr
*)0) {
108 fprintf(stderr
, "[%s:%s] Can't create text object circular buffer\n",
115 * Now that we have the private structures allocated, set them up.
117 text_data
->llrock
= (int *)0;
118 text_data
->numLines
= text_onp
->o_height
;
119 text_data
->cbHdr
= newCB
;
120 text_data
->firstEntShown
= 0;
121 text_data
->lastEntShown
= 0;
123 fprintf(stderr
, "[%s:%s] Number of lines in window: %d: ", mn
, rn
,
124 text_data
->numLines
);
127 * Attach the text-specific private
128 * data to the generic onode and return the happy news.
130 text_onp
->o_data
= (int *)text_data
;
133 } /*gator_text_create */
135 /*------------------------------------------------------------------------
139 * Destroy a gator text object.
142 * struct onode *onp : Ptr to the text onode to delete.
146 * Error value otherwise.
149 * Nothing interesting.
153 *------------------------------------------------------------------------*/
156 gator_text_destroy(struct onode
*onp
)
157 { /*gator_text_destroy */
160 * For now, this is a no-op.
164 } /*gator_text_destroy */
166 /*------------------------------------------------------------------------
170 * Display/redraw a gator text object.
173 * struct onode *onp: Ptr to the text onode to display.
177 * Error value otherwise.
180 * Nothing interesting.
184 *------------------------------------------------------------------------*/
187 gator_text_display(struct onode
*onp
)
188 { /*gator_text_display */
190 static char rn
[] = "gator_text_display"; /*Routine name */
191 struct gator_textobj
*text_data
; /*Ptr to text obj data */
192 struct gator_textcb_hdr
*cbHdr
; /*Ptr to CB header */
193 struct gwin_strparams strparams
; /*String-drawing params */
194 int currLine
; /*Current line being updated */
195 int currLinesUsed
; /*Num screen lines used */
196 int currIdx
; /*Current line index */
197 int currEnt
; /*Current entry being drawn */
198 struct gator_textcb_entry
*curr_ent
; /*Ptr to current entry */
201 fprintf(stderr
, "[%s:%s] Displaying text object at %p\n", mn
, rn
,
203 text_data
= (struct gator_textobj
*)(onp
->o_data
);
204 cbHdr
= text_data
->cbHdr
;
207 "[%s:%s] Displaying text object at %p, object-specific data at %p\n",
208 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;
216 (cbHdr
->oldestEntIdx
+
217 (currEnt
- cbHdr
->oldestEnt
)) % cbHdr
->maxEntriesStored
;
218 curr_ent
= cbHdr
->entry
+ currIdx
;
222 "[%s:%s] Drawing %d populated lines, starting with entry %d (index %d) at %p",
223 mn
, rn
, currLinesUsed
, currEnt
, currIdx
, curr_ent
);
225 strparams
.x
= onp
->o_x
;
226 strparams
.y
= onp
->o_y
;
227 for (currLine
= 0; currLine
< text_data
->numLines
; currLine
++) {
229 * Draw the current entry.
231 if (currLinesUsed
> 0) {
233 * Drawing a populated line. We need to iterate if there are
234 * inversions (I don't feel like doing this now).
236 strparams
.s
= curr_ent
->textp
;
237 strparams
.highlight
= curr_ent
->highlight
;
238 WOP_DRAWSTRING(onp
->o_window
, &strparams
);
243 if (currIdx
>= cbHdr
->maxEntriesStored
) {
245 curr_ent
= cbHdr
->entry
;
252 strparams
.s
= cbHdr
->blankLine
;
253 strparams
.highlight
= 0;
254 WOP_DRAWSTRING(onp
->o_window
, &strparams
);
258 * Adjust the X and Y locations.
266 * Box the window before we leave.
268 #if GATOR_TEXTCB_DO_BOX
270 fprintf(stderr
, "[%s:%s] Boxing window structure at 0x%x\n", mn
, rn
,
272 WOP_BOX(onp
->o_window
);
273 #endif /* GATOR_TEXTCB_DO_BOX */
276 * For now, this is all we do.
280 } /*gator_text_display */
282 /*------------------------------------------------------------------------
286 * Drop the refcount on a gator text object.
289 * struct onode *onp : Ptr to the onode whose refcount is
294 * Error value otherwise.
297 * Nothing interesting.
301 *------------------------------------------------------------------------*/
304 gator_text_release(struct onode
*onp
)
305 { /*gator_text_release */
308 * For now, this is a no-op.
312 } /*gator_text_release */
314 /*------------------------------------------------------------------------
318 * Scroll a text object some number of lines.
321 * struct onode *onp : Ptr to the text onode to be scrolled.
322 * int nlines : Number of lines to scroll.
323 * int direction : Scroll up or down?
327 * Error value otherwise.
330 * Invariant: the text object's firstEntShown and lastEntShown
331 * are always between oldestEnt and currEnt (inclusive).
335 *------------------------------------------------------------------------*/
338 gator_text_Scroll(struct onode
*onp
, int nlines
, int direction
)
339 { /*gator_text_Scroll */
341 static char rn
[] = "gator_text_Scroll"; /*Routine name */
342 struct gator_textobj
*text_data
; /*Ptr to text obj data */
345 * We move the markers for first & last entries displayed, depending
346 * on what's available to us in the circular buffer. We never leave
350 fprintf(stderr
, "[%s:%s] Scrolling text object %d lines %s\n",
352 (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 *------------------------------------------------------------------------*/
415 gator_text_Write(struct onode
*onp
, char *strToWrite
, int numChars
,
416 int highlight
, int skip
)
417 { /*gator_text_Write */
419 static char rn
[] = "gator_text_Write"; /*Routine name */
420 int code
; /*Return value on routines */
421 struct gator_textobj
*text_data
; /*Ptr to text obj data */
422 struct gator_textcb_hdr
*cbHdr
; /*Ptr to text CB header */
423 int i
; /*Loop variable */
424 int oldCurrEnt
; /*CB's old currEnt value */
425 int redisplay
; /*Redisplay after write? */
426 int shownDiff
; /*Diff between 1st & last lines */
427 int writeDiff
; /*Num lines really written */
428 int bumpAmount
; /*Amount to bump count */
435 "[%s:%s] Writing %d chars to text object at %p (highlight=%d, skip=%d: '",
436 mn
, rn
, numChars
, onp
, highlight
, skip
);
437 for (i
= 0; i
< numChars
; i
++)
438 fprintf(stderr
, "%c", strToWrite
[i
]);
439 fprintf(stderr
, "\n");
443 numChars
= strlen(strToWrite
); /* simplify caller */
444 text_data
= (struct gator_textobj
*)(onp
->o_data
);
445 cbHdr
= text_data
->cbHdr
;
446 if (cbHdr
== (struct gator_textcb_hdr
*)0) {
447 fprintf(stderr
, "[%s:%s] Text object missing its circular buffer!\n",
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
)) {
459 "[%s:%s] Current entry is on screen. Tracking this write\n",
461 oldCurrEnt
= cbHdr
->currEnt
;
466 "[%s:%s] Current entry NOT on screen, not tracking write\n",
474 * We're tracking the write. Compute the number of screen lines
475 * actually written and adjust our own numbers, then call the
478 shownDiff
= text_data
->lastEntShown
- text_data
->firstEntShown
;
479 writeDiff
= cbHdr
->currEnt
- oldCurrEnt
;
482 "[%s:%s] Preparing to redisplay. Difference in shown lines=%d, difference in written lines=%d\n",
483 mn
, rn
, shownDiff
, writeDiff
);
484 if (shownDiff
< (text_data
->numLines
- 1)) {
486 * We weren't showing a full screen of stuff. Bump the last
487 * line shown by the minimum of the number of free lines still
488 * on the screen and the number of new lines actually written.
490 bumpAmount
= (text_data
->numLines
- 1) - shownDiff
;
491 if (writeDiff
< bumpAmount
)
492 bumpAmount
= writeDiff
;
493 text_data
->lastEntShown
+= bumpAmount
;
494 writeDiff
-= bumpAmount
;
497 "[%s:%s] Empty lines appeared on screen, bumping bottom line shown by %d; new writeDiff is %d\n",
498 mn
, rn
, bumpAmount
, writeDiff
);
502 * If we have any more lines that were written not taken care
503 * of by the above, we just bump the counters.
508 "[%s:%s] Still more lines need to be tracked. Moving first & last shown down by %d\n",
510 text_data
->firstEntShown
+= writeDiff
;
511 text_data
->lastEntShown
+= writeDiff
;
515 /*Redisplay needed */
517 * Simply call the circular buffer write op.
519 code
= gator_textcb_Write(cbHdr
, strToWrite
, numChars
, highlight
, skip
);
522 "[%s:%s] Can't write to text object's circular buffer, errror code is %d\n",
528 * Everything went well. Return the happy news.
532 } /*gator_text_Write */
534 /*------------------------------------------------------------------------
535 * gator_text_BlankLine
538 * Write a given number of blank lines to the given text object.
541 * struct onode *onp : Ptr to the onode to which we're writing.
542 * int numBlanks : Number of blank lines to write.
546 * Error value otherwise.
549 * Nothing interesting.
553 *------------------------------------------------------------------------*/
556 gator_text_BlankLine(struct onode
*onp
, int numBlanks
)
557 { /*gator_text_BlankLine */
559 static char rn
[] = "gator_text_BlankLine"; /*Routine name */
560 int code
; /*Return value on routines */
561 struct gator_textobj
*text_data
; /*Ptr to text obj data */
564 * We just call the circular buffer routine directly.
568 "[%s:%s] Writing %d blank lines to text object at %p\n", mn
,
571 text_data
= (struct gator_textobj
*)(onp
->o_data
);
572 code
= gator_textcb_BlankLine(text_data
->cbHdr
, numBlanks
);
575 "[%s:%s] Can't write %d blank lines to text object at %p\n",
576 mn
, rn
, numBlanks
, onp
);
581 * Blank lines written successfully. Adjust what lines are currently
582 * shown. Iff we were tracking the end of the buffer, we have to
583 * follow the blank lines.
585 if (text_data
->lastEntShown
== text_data
->cbHdr
->currEnt
- numBlanks
) {
586 text_data
->firstEntShown
+= numBlanks
;
587 text_data
->lastEntShown
+= numBlanks
;
591 * Return the happy news.
595 } /*gator_text_BlankLine */