|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 11166 (0x2b9e)
Types: TextFile
Names: »screen.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/elm/src/screen.c«
/** screen.c **/
/** screen display routines for ELM program
(C) Copyright 1985, Dave Taylor
**/
#include "headers.h"
#define minimum(a,b) ((a) < (b) ? (a) : (b))
static int last_current = -1;
char *strcpy(), *strncpy(), *nameof();
showscreen()
{
char buffer[SLEN];
ClearScreen();
if (selected)
sprintf(buffer,
"Mailbox is '%s' with %d shown out of %d [Elm %s]",
nameof(infile), selected, message_count, VERSION);
else
sprintf(buffer, "Mailbox is '%s' with %d message%s [Elm %s]",
nameof(infile), message_count, plural(message_count), VERSION);
Centerline(1, buffer);
last_header_page = -1; /* force a redraw regardless */
show_headers();
if (mini_menu)
show_menu();
show_last_error();
if (hp_terminal)
define_softkeys(MAIN);
}
update_title()
{
/** display a new title line, probably due to new mail arriving **/
char buffer[SLEN];
if (selected)
sprintf(buffer,
"Mailbox is '%s' with %d shown out of %d [Elm %s]",
nameof(infile), selected, message_count, VERSION);
else
sprintf(buffer, "Mailbox is '%s' with %d message%s [Elm %s]",
nameof(infile), message_count, plural(message_count), VERSION);
ClearLine(1);
Centerline(1, buffer);
}
show_menu()
{
/** write main system menu... **/
if (user_level == 0) { /* a rank beginner. Give less options */
Centerline(LINES-7,
"You can use any of the following commands by pressing the first character;");
Centerline(LINES-6,
"D)elete mail, M)ail a message, R)eply to mail, U)ndelete, or Q)uit");
Centerline(LINES-5,
"To read a message, press <return>. j = move arrow down, k = move arrow up");
} else {
Centerline(LINES-7,
"|=pipe, !=shell, ?=help, <n>=set current to n, /=search pattern");
Centerline(LINES-6,
"A)lias, C)hange mailbox, D)elete, E)dit, F)orward, G)roup reply, M)ail,");
Centerline(LINES-5,
"N)ext, O)ptions, P)rint, R)eply, S)ave, T)ag, Q)uit, U)ndelete, or eX)it");
}
}
int
show_headers()
{
/** Display page of headers (10) if present. First check to
ensure that header_page is in bounds, fixing silently if not.
If out of bounds, return zero, else return non-zero
Modified to only show headers that are "visible" to ze human
person using ze program, eh?
**/
register int this_msg = 0, line = 4, last = 0, last_line,
displayed = 0;
char newfrom[SLEN], buffer[SLEN];
if (fix_header_page()) {
dprint0(7, "show_headers returned FALSE 'cause of fix-header-page\n");
return(FALSE);
}
if (selected) {
if ((header_page*headers_per_page) > selected) {
dprint2(7, "show_headers returned FALSE since selected [%d] < %d\n",
selected, header_page*headers_per_page);
return(FALSE); /* too far! too far! */
}
dprint0(6,"** show_headers AND selected...\n");
if (header_page == 0) {
this_msg = visible_to_index(1);
displayed = 0;
}
else {
this_msg = visible_to_index(header_page * headers_per_page + 1);
displayed = header_page * headers_per_page;
}
dprint2(7,"this_msg (index) = %d [header_page = %d]\n", this_msg,
header_page);
dprint1(7,"we've already displayed %d messages\n", displayed);
last = displayed+headers_per_page;
dprint1(7,"and the last msg on this page is %d\n", last);
}
else {
if (header_page == last_header_page) /* nothing to do! */
return(FALSE);
/** compute last header to display **/
this_msg = header_page * headers_per_page;
last = this_msg + (headers_per_page - 1);
}
if (last >= message_count) last = message_count-1;
/** Okay, now let's show the header page! **/
ClearLine(line); /* Clear the top line... */
MoveCursor(line, 0); /* and move back to the top of the page... */
while ((selected && displayed < last) || this_msg <= last) {
tail_of(header_table[this_msg].from, newfrom, TRUE);
if (selected) {
if (this_msg == current-1)
build_header_line(buffer, &header_table[this_msg], ++displayed,
TRUE, newfrom);
else
build_header_line(buffer, &header_table[this_msg],
++displayed, FALSE, newfrom);
}
else {
if (this_msg == current-1)
build_header_line(buffer, &header_table[this_msg], this_msg+1,
TRUE, newfrom);
else
build_header_line(buffer, &header_table[this_msg],
this_msg+1, FALSE, newfrom);
}
Write_to_screen("%s\r\n", 1, buffer); /* avoid '%' probs */
CleartoEOLN();
line++; /* for clearing up in a sec... */
if (selected) {
if ((this_msg = next_visible(this_msg+1)-1) < 0)
break; /* GET OUTTA HERE! */
/* the preceeding looks gross because we're using an INDEX
variable to pretend to be a "current" counter, and the
current counter is always 1 greater than the actual
index. Does that make sense??
*/
}
else
this_msg++; /* even dumber... */
}
dprint0(1,"** out of redraw loop! **\n");
if (mini_menu)
last_line = LINES-8;
else
last_line = LINES-3;
while (line < last_line) {
CleartoEOLN();
Writechar('\r');
Writechar('\n');
line++;
}
display_central_message();
last_current = current;
last_header_page = header_page;
return(TRUE);
}
show_current()
{
/** Show the new header, with all the usual checks **/
register int first = 0, last = 0, last_line, new_line, i=0, j=0;
char newfrom[SLEN], old_buffer[SLEN], new_buffer[SLEN];
(void) fix_header_page(); /* Who cares what it does? ;-) */
/** compute last header to display **/
first = header_page * headers_per_page;
last = first + (headers_per_page - 1);
if (last > message_count)
last = message_count;
/** okay, now let's show the pointers... **/
/** have we changed??? **/
if (current == last_current)
return;
if (selected) {
dprint2(2,"\nshow_current\n* last_current = %d, current = %d\n",
last_current, current);
last_line = ((i=compute_visible(last_current-1)-1) %
headers_per_page)+4;
new_line = ((j=compute_visible(current-1)-1) % headers_per_page)+4;
dprint1(2,"* compute_visible(last-1)=%d\n",
compute_visible(last_current-1));
dprint1(2,"* compute_visible(current-1)=%d\n",
compute_visible(current-1));
dprint2(2,"* ending up with last_line = %d and new_line = %d\n",
last_line, new_line);
}
else {
last_line = ((last_current-1) % headers_per_page)+4;
new_line = ((current-1) % headers_per_page)+4;
}
dprint4(7,
"--> show-current: last_current=%d [%d] and current=%d [%d]\n",
last_current, i, current, j);
dprint2(7," maps to lines %d and %d\n", last_line, new_line);
if (has_highlighting && ! arrow_cursor) {
/** build the old and new header lines... **/
tail_of(header_table[current-1].from, newfrom, TRUE);
build_header_line(new_buffer, &header_table[current-1],
(selected? compute_visible(current-1) : current),
TRUE, newfrom);
if (last_current > 0) { /* say we went from no mail to new... */
tail_of(header_table[last_current-1].from, newfrom, TRUE);
build_header_line(old_buffer, &header_table[last_current-1],
(selected? compute_visible(last_current-1) : last_current),
FALSE, newfrom);
ClearLine(last_line);
PutLine0(last_line, 0, old_buffer);
}
PutLine0(new_line, 0, new_buffer);
}
else {
if (on_page(last_current))
PutLine0(last_line,0," "); /* remove old pointer... */
if (on_page(current))
PutLine0(new_line, 0,"->");
}
last_current = current;
}
build_header_line(buffer, entry, message_number, highlight, from)
char *buffer;
struct header_rec *entry;
int message_number, highlight;
char *from;
{
/** Build in buffer the message header ... entry is the current
message entry, 'from' is a modified (displayable) from line,
'highlight' is either TRUE or FALSE, and 'message_number'
is the number of the message.
**/
/** Note: using 'strncpy' allows us to output as much of the
subject line as possible given the dimensions of the screen.
The key is that 'strncpy' returns a 'char *' to the string
that it is handing to the dummy variable! Neat, eh? **/
char subj[LONG_SLEN], /* to output subject */
buff[NLEN]; /* keep start_highlight value */
if (strcmp(start_highlight,"->") != 0 && arrow_cursor) {
strcpy(buff, start_highlight);
strcpy(start_highlight, "->");
}
strncpy(subj, entry->subject, COLUMNS-45);
subj[COLUMNS-45] = '\0'; /* insurance, eh? */
/* now THIS is a frightening format statement!!! */
sprintf(buffer, "%s%s%c%c%c%-3d %3.3s %-2d %-18.18s (%d) %s%s%s",
highlight? ((has_highlighting && !arrow_cursor) ?
start_highlight : "->") : " ",
(highlight && has_highlighting && !arrow_cursor)? " " : "",
show_status(entry->status),
(entry->status & DELETED? 'D' : ' '),
(entry->status & TAGGED? '+' : ' '),
message_number,
entry->month,
atoi(entry->day),
from,
entry->lines,
(entry->lines / 1000 > 0? "" : /* spacing the */
entry->lines / 100 > 0? " " : /* same for the */
entry->lines / 10 > 0? " " : /* lines in () */
" "), /* [wierd] */
subj,
(highlight && has_highlighting && !arrow_cursor) ?
end_highlight : "");
/** Actually, it's rather an impressive feat that we can
do so much in essentially one statement! (Of course,
I'll bet the test suite for the printf routine isn't
THIS rigorous either!!!) (to be honest, though, just
looking at this statement makes me chuckle...)
**/
if (arrow_cursor) /* restore! */
strcpy(start_highlight, buff);
}
int
fix_header_page()
{
/** this routine will check and ensure that the current header
page being displayed contains messages! It will silently
fix 'header-page' if wrong. Returns TRUE if changed. **/
int last_page, old_header;
old_header = header_page;
last_page = (int) ((message_count-1) / headers_per_page);
if (header_page > last_page)
header_page = last_page;
else if (header_page < 0)
header_page = 0;
return(old_header != header_page);
}
int
on_page(message)
int message;
{
/** Returns true iff the specified message is on the displayed page. **/
dprint1(6,"** on_page(%d) returns...", message);
if (selected) message = compute_visible(message-1);
if (message >= header_page * headers_per_page)
if (message <= ((header_page+1) * headers_per_page)) {
dprint0(6,"TRUE\n");
return(TRUE);
}
dprint0(6,"FALSE\n");
return(FALSE);
}
show_status(status)
int status;
{
/** This routine returns a single character indicative of
the status of this message. The precedence is;
F = form letter
E = Expired message
P = Priority message
A = Action associated with message
N = New message
_ = (space) default
**/
if (status & FORM_LETTER) return( 'F' );
else if (status & EXPIRED) return( 'E' );
else if (status & PRIORITY) return( 'P' );
else if (status & ACTION) return( 'A' );
else if (status & NEW) return( 'N' );
else return( ' ' );
}