|
|
1.1 root 1: #line 1 "CON_OUT.C"
2:
3: /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
4:
5: /**********************************************************************/
6: /* Functions that pertain to console i/o - color, strings, chars etc. */
7: /* Called from functions everywhere */
8: /**********************************************************************/
9:
10: #include "sbbs.h"
11:
12: extern char *mnestr;
13:
14: /***************************************************/
15: /* Seven bit table for EXASCII to ASCII conversion */
16: /***************************************************/
17: char *sbtbl="CUeaaaaceeeiiiAAEaAooouuyOUcLYRfaiounNao?--24!<>"
18: "###||||++||++++++--|-+||++--|-+----++++++++##[]#"
19: "abrpEout*ono%0ENE+><rj%=o..+n2* ";
20:
21: char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
22: char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
23: ,"Jul","Aug","Sep","Oct","Nov","Dec"};
24:
25: uchar outchar_esc=0;
26:
27: #ifdef __WIN32__
28:
29: int lclatr(int atr)
30: {
31:
32: textattr(atr);
33: return(curatr);
34: }
35:
36: void lputc(ch)
37: {
38: switch(ch) {
39: case CLREOL:
40: clreol();
41: break;
42: case FF:
43: clrscr();
44: break;
45: case TAB:
46: if(!(wherex()%8))
47: putchar(SP);
48: while(wherex()%8)
49: putchar(SP);
50: break;
51: default:
52: putchar(ch);
53: break; }
54: }
55:
56: #endif
57:
58: #ifdef __OS2__
59:
60: HEV con_out_sem; /* Console command semaphore */
61:
62: #define CON_OUT_BUFLEN 8192 /* Console output (ANSI) buffer */
63: #define CON_BLK_BUFLEN 4096 /* Console block (all same atr) buffer */
64:
65: uchar conoutbuf[CON_OUT_BUFLEN];
66: uchar conblkbuf[CON_BLK_BUFLEN];
67: volatile uint conblkcnt=0;
68: volatile uint conoutbot=0;
69: volatile uint conouttop=0;
70:
71: uchar lcl_curatr=LIGHTGRAY;
72:
73: /****************************************************************************/
74: /* Prints one block of text (all same attribute) at current cursor position */
75: /****************************************************************************/
76: void print_conblkbuf()
77: {
78: conblkbuf[conblkcnt]=0;
79: cputs(conblkbuf);
80: conblkcnt=0;
81: }
82:
83: void con_outch(int ch)
84: {
85: static uchar ansi_esc;
86: static uchar ansi_curval;
87: static uchar ansi_val[3];
88: static uchar ansi_x;
89: static uchar ansi_y;
90: int x,y;
91:
92: if(ch==ESC) {
93: ansi_esc=1;
94: ansi_val[0]=ansi_val[1]=ansi_val[2]=ansi_curval=0;
95: return; }
96:
97: if(ansi_esc==1) { /* Received ESC already */
98: if(ch=='[') {
99: ansi_esc++;
100: return; }
101: ansi_esc=ansi_val[0]=ansi_val[1]=ansi_val[2]=ansi_curval=0; }
102:
103: if(ansi_esc==2) { /* Received ESC[ already */
104:
105: if(isdigit(ch)) {
106: if(ansi_curval>2) ansi_curval=0;
107: ansi_val[ansi_curval]*=10;
108: ansi_val[ansi_curval]+=ch&0xf;
109: return; }
110:
111: if(ch==';') {
112: ansi_curval++;
113: return; }
114:
115: /* looks like valid ANSI, so purge the output block */
116: if(conblkcnt)
117: print_conblkbuf();
118: switch(ch) {
119: case 'A': // Move cursor up
120: y=wherey();
121: if(ansi_val[0])
122: y-=ansi_val[0];
123: else
124: y--;
125: if(y<1) y=1;
126: gotoxy(wherex(),y);
127: break;
128: case 'B': // Move cursor down
129: y=wherey();
130: if(ansi_val[0])
131: y+=ansi_val[0];
132: else
133: y++;
134: if(y>node_scrnlen) y=node_scrnlen;
135: gotoxy(wherex(),y);
136: break;
137: case 'C': // Move cursor right
138: x=wherex();
139: if(ansi_val[0])
140: x+=ansi_val[0];
141: else
142: x++;
143: if(x>80) x=80;
144: gotoxy(x,wherey());
145: break;
146: case 'D': // Move cursor left
147: x=wherex();
148: if(ansi_val[0])
149: x-=ansi_val[0];
150: else
151: x--;
152: if(x<1) x=1;
153: gotoxy(x,wherey());
154: break;
155: case 'J': // clear screen
156: if(ansi_val[0]==2)
157: clrscr();
158: break;
159: case 'K': // clearn from cursor to end of line
160: clreol();
161: break;
162: case 'H': // Position cursor
163: case 'f':
164: y=ansi_val[0];
165: x=ansi_val[1];
166: if(x<1) x=1;
167: if(x>80) x=80;
168: if(y<1) y=1;
169: if(y>node_scrnlen) y=node_scrnlen;
170: gotoxy(x,y);
171: break;
172: case 's': // Save cursor position
173: ansi_x=wherex();
174: ansi_y=wherey();
175: break;
176: case 'u': // Restore cursor position
177: if(ansi_x)
178: gotoxy(ansi_x,ansi_y);
179: break;
180: case 'm': // Select character attributes
181: for(x=0;x<=ansi_curval;x++)
182: switch(ansi_val[x]) {
183: case 0: // no special attributes
184: case 8: // concealed text (no display)
185: lcl_curatr=LIGHTGRAY;
186: break;
187: case 1: // high intensity
188: case 3: // italic
189: case 4: // underline
190: lcl_curatr|=HIGH;
191: break;
192: case 2: // low intensity
193: lcl_curatr&=~HIGH;
194: break;
195: case 5: // blink
196: case 6: // rapid blink
197: case 7: // reverse video
198: lcl_curatr|=BLINK;
199: break;
200: case 30: // foreground black
201: lcl_curatr&=0xf8;
202: lcl_curatr|=BLACK;
203: break;
204: case 31: // foreground red
205: lcl_curatr&=0xf8;
206: lcl_curatr|=RED;
207: break;
208: case 32: // foreground green
209: lcl_curatr&=0xf8;
210: lcl_curatr|=GREEN;
211: break;
212: case 33: // foreground yellow
213: lcl_curatr&=0xf8;
214: lcl_curatr|=BROWN;
215: break;
216: case 34: // foreground blue
217: lcl_curatr&=0xf8;
218: lcl_curatr|=BLUE;
219: break;
220: case 35: // foreground magenta
221: lcl_curatr&=0xf8;
222: lcl_curatr|=MAGENTA;
223: break;
224: case 36: // foreground cyan
225: lcl_curatr&=0xf8;
226: lcl_curatr|=CYAN;
227: break;
228: case 37: // foreground white
229: lcl_curatr&=0xf8;
230: lcl_curatr|=LIGHTGRAY;
231: break;
232: case 40: // background black
233: lcl_curatr&=0x8f;
234: lcl_curatr|=(BLACK<<4);
235: break;
236: case 41: // background red
237: lcl_curatr&=0x8f;
238: lcl_curatr|=(RED<<4);
239: break;
240: case 42: // background green
241: lcl_curatr&=0x8f;
242: lcl_curatr|=(GREEN<<4);
243: break;
244: case 43: // background yellow
245: lcl_curatr&=0x8f;
246: lcl_curatr|=(BROWN<<4);
247: break;
248: case 44: // background blue
249: lcl_curatr&=0x8f;
250: lcl_curatr|=(BLUE<<4);
251: break;
252: case 45: // background magenta
253: lcl_curatr&=0x8f;
254: lcl_curatr|=(MAGENTA<<4);
255: break;
256: case 46: // background cyan
257: lcl_curatr&=0x8f;
258: lcl_curatr|=(CYAN<<4);
259: break;
260: case 47: // background white
261: lcl_curatr&=0x8f;
262: lcl_curatr|=(LIGHTGRAY<<4);
263: break; }
264: textattr(lcl_curatr);
265: break; }
266:
267: ansi_esc=ansi_val[0]=ansi_val[1]=ansi_val[2]=ansi_curval=0;
268: return; }
269:
270: if(conblkcnt+1>=CON_BLK_BUFLEN)
271: print_conblkbuf();
272: switch(ch) {
273: case CLREOL:
274: if(conblkcnt) print_conblkbuf();
275: clreol();
276: break;
277: case FF:
278: if(conblkcnt) print_conblkbuf();
279: clrscr();
280: break;
281: case TAB:
282: if(conblkcnt) print_conblkbuf();
283: if(!(wherex()%8))
284: putch(SP);
285: while(wherex()%8)
286: putch(SP);
287: break;
288: default:
289: conblkbuf[conblkcnt++]=ch;
290: break; }
291: }
292:
293:
294: /****************************************************************************/
295: /* Thread that services the console output buffer (conoutbuf) which */
296: /* contains ANSI escape sequences */
297: /* All output is for the text window (mirroring the remote console) */
298: /****************************************************************************/
299: void con_out_thread(void *unused)
300: {
301: int i,top,cnt;
302: ulong l;
303:
304: while(1) {
305: mswait(1);
306: if(conoutbot==conouttop) {
307: DosWaitEventSem(con_out_sem,10000); /* every 10 seconds */
308: DosResetEventSem(con_out_sem,&l);
309: continue; }
310: top=conouttop;
311: if(top<conoutbot)
312: cnt=CON_OUT_BUFLEN-conoutbot;
313: else
314: cnt=top-conoutbot;
315: for(i=conoutbot;i<conoutbot+cnt;i++)
316: con_outch(conoutbuf[i]);
317: conoutbot=i;
318: if(conblkcnt)
319: print_conblkbuf();
320: if(conoutbot==CON_OUT_BUFLEN)
321: conoutbot=0; }
322: }
323:
324:
325:
326: void outcon(char ch)
327: {
328: int i=conouttop+1;
329:
330: if(i==CON_OUT_BUFLEN)
331: i=0;
332: while(conoutbot==i) // Wait for thread to service queue
333: mswait(1);
334: conoutbuf[conouttop++]=ch;
335: if(conouttop==CON_OUT_BUFLEN)
336: conouttop=0;
337: DosPostEventSem(con_out_sem); // Enable output
338: }
339:
340: int outcon_pending()
341: {
342: if(conoutbot!=conouttop)
343: return(1);
344: if(conblkcnt) {
345: print_conblkbuf();
346: return(1); }
347: return(0);
348: }
349:
350: int conaes()
351: {
352: return(outchar_esc==2);
353: }
354:
355: void lputc(int ch)
356: {
357:
358: while(outcon_pending())
359: mswait(1);
360: switch(ch) {
361: case CLREOL:
362: clreol();
363: break;
364: case FF:
365: clrscr();
366: break;
367: case TAB:
368: if(!(wherex()%8))
369: putch(SP);
370: while(wherex()%8)
371: putch(SP);
372: break;
373: default:
374: putch(ch);
375: break; }
376: }
377:
378: long lputs(char *str)
379: {
380: while(outcon_pending())
381: mswait(1);
382: return(cputs(str));
383: }
384:
385: int lclwx(void)
386: {
387: while(outcon_pending())
388: mswait(1);
389: return(wherex());
390: }
391:
392: int lclwy(void)
393: {
394: while(outcon_pending())
395: mswait(1);
396: return(wherey());
397: }
398:
399: void lclxy(int x, int y)
400: {
401: while(outcon_pending())
402: mswait(1);
403: gotoxy(x,y);
404: }
405:
406: int lclatr(int x)
407: {
408: int i;
409:
410: while(conoutbot!=conouttop) /* wait for output buf to empty */
411: mswait(1);
412: if(x==-1)
413: return(lcl_curatr);
414:
415: textattr(x);
416: i=lcl_curatr;
417: lcl_curatr=x;
418: return(i); /* Return previous attribute */
419: }
420:
421: #endif
422:
423: /****************************************************************************/
424: /* Outputs a NULL terminated string locally and remotely (if applicable) */
425: /* Handles ctrl-a characters */
426: /****************************************************************************/
427: int bputs(char *str)
428: {
429: int i;
430: ulong l=0;
431:
432: while(str[l]) {
433: if(str[l]==1) { /* ctrl-a */
434: ctrl_a(str[++l]); /* skip the ctrl-a */
435: l++; /* skip the attribute code */
436: continue; }
437: if(str[l]=='@') { /* '@' */
438: if(str==mnestr /* Mnemonic string or */
439: || (str>=text[0] /* Straight out of TEXT.DAT */
440: && str<=text[TOTAL_TEXT-1])) {
441: i=atcodes(str+l); /* return 0 if not valid @ code */
442: l+=i; /* i is length of code string */
443: if(i) /* if valid string, go to top */
444: continue; }
445: for(i=0;i<TOTAL_TEXT;i++)
446: if(str==text[i])
447: break;
448: if(i<TOTAL_TEXT) { /* Replacement text */
449: //lputc(7);
450: i=atcodes(str+l);
451: l+=i;
452: if(i)
453: continue; } }
454: outchar(str[l++]); }
455: return(l);
456: }
457:
458: /****************************************************************************/
459: /* Outputs a NULL terminated string locally and remotely (if applicable) */
460: /* Does not expand ctrl-a characters (raw) */
461: /* Max length of str is 64 kbytes */
462: /****************************************************************************/
463: int rputs(char *str)
464: {
465: ulong l=0;
466:
467: while(str[l])
468: outchar(str[l++]);
469: return(l);
470: }
471:
472: /****************************************************************************/
473: /* Performs printf() through local assembly routines */
474: /* Called from everywhere */
475: /****************************************************************************/
476: int lprintf(char *fmat, ...)
477: {
478: va_list argptr;
479: char sbuf[256];
480: int chcount;
481:
482: va_start(argptr,fmat);
483: chcount=vsprintf(sbuf,fmat,argptr);
484: va_end(argptr);
485: lputs(sbuf);
486: return(chcount);
487: }
488:
489: /****************************************************************************/
490: /* Performs printf() using bbs bputs function */
491: /****************************************************************************/
492: int bprintf(char *fmt, ...)
493: {
494: va_list argptr;
495: char sbuf[1024];
496:
497: if(!strchr(fmt,'%'))
498: return(bputs(fmt));
499: va_start(argptr,fmt);
500: vsprintf(sbuf,fmt,argptr);
501: va_end(argptr);
502: return(bputs(sbuf));
503: }
504:
505: /****************************************************************************/
506: /* Performs printf() using bbs rputs function */
507: /****************************************************************************/
508: int rprintf(char *fmt, ...)
509: {
510: va_list argptr;
511: char sbuf[1024];
512:
513: va_start(argptr,fmt);
514: vsprintf(sbuf,fmt,argptr);
515: va_end(argptr);
516: return(rputs(sbuf));
517: }
518:
519: /****************************************************************************/
520: /* Outputs character locally and remotely (if applicable), preforming echo */
521: /* translations (X's and r0dent emulation) if applicable. */
522: /****************************************************************************/
523: void outchar(char ch)
524: {
525: char lch;
526: int i;
527:
528: if(console&CON_ECHO_OFF)
529: return;
530: if(ch==ESC)
531: outchar_esc=1;
532: else if(outchar_esc==1) {
533: if(ch=='[')
534: outchar_esc++;
535: else
536: outchar_esc=0; }
537: else
538: outchar_esc=0;
539: if(useron.misc&NO_EXASCII && ch&0x80)
540: ch=sbtbl[(uchar)ch^0x80]; /* seven bit table */
541: if(ch==FF && lncntr>1 && !tos) {
542: lncntr=0;
543: CRLF;
544: pause();
545: while(lncntr && online && !(sys_status&SS_ABORT))
546: pause(); }
547: if(sys_status&SS_CAP /* Writes to Capture File */
548: && (sys_status&SS_ANSCAP || (ch!=ESC && !lclaes())))
549: fwrite(&ch,1,1,capfile);
550: if(console&CON_L_ECHO) {
551: if(console&CON_L_ECHOX && (uchar)ch>=SP)
552: outcon('X');
553: else if(node_misc&NM_NOBEEP && ch==7); /* Do nothing if beep */
554: else if(ch==7) {
555: beep(2000,110);
556: nosound(); }
557: else outcon(ch); }
558: if(online==ON_REMOTE && console&CON_R_ECHO) {
559: if(console&CON_R_ECHOX && (uchar)ch>=SP)
560: ch='X';
561: i=0;
562: while(outcom(ch)&TXBOF && i<1440) { /* 3 minute pause delay */
563:
564: if(lkbrd(1)) {
565: lch=lkbrd(0); /* ctrl-c */
566: if(lch==3) {
567: lputs("local abort (outchar)\r\n");
568: i=1440;
569: break; }
570: ungetkey(lch); }
571: if(!DCDHIGH)
572: break;
573: i++;
574: if(sys_status&SS_SYSPAGE)
575: beep(i,80);
576: else
577: mswait(80); }
578: if(i==1440) { /* timeout - beep flush outbuf */
579: i=rioctl(TXBC);
580: lprintf("timeout(outchar) %04X %04X\r\n",i,rioctl(IOFO));
581: outcom(7);
582: lputc(7);
583: rioctl(IOCS|PAUSE); } }
584: if(ch==LF) {
585: lncntr++;
586: lbuflen=0;
587: tos=0; }
588: else if(ch==FF) {
589: lncntr=0;
590: lbuflen=0;
591: tos=1; }
592:
593: else {
594: if(!lbuflen)
595: latr=curatr;
596: if(lbuflen<LINE_BUFSIZE)
597: lbuf[lbuflen++]=ch; }
598:
599: if(lncntr==rows-1 && ((useron.misc&UPAUSE && !(sys_status&SS_PAUSEOFF))
600: || sys_status&SS_PAUSEON)) {
601: lncntr=0;
602: pause(); }
603:
604: }
605:
606:
607: /****************************************************************************/
608: /* performs the correct attribute modifications for the Ctrl-A code */
609: /****************************************************************************/
610: void ctrl_a(char x)
611: {
612: int i,j;
613: char tmp1[128],atr=curatr;
614:
615: if(x && (uchar)x<ESC) { /* Ctrl-A through Ctrl-Z for users with MF only */
616: if(!(useron.flags1&FLAG(x+64)))
617: console^=(CON_ECHO_OFF);
618: return; }
619: if((uchar)x>=0x7f) {
620: if(useron.misc&ANSI)
621: bprintf("\x1b[%uC",(uchar)x-0x7f);
622: else
623: for(i=0;i<(uchar)x-0x7f;i++)
624: outchar(SP);
625: return; }
626: switch(toupper(x)) {
627: case '!': /* level 10 or higher */
628: if(useron.level<10)
629: console^=CON_ECHO_OFF;
630: break;
631: case '@': /* level 20 or higher */
632: if(useron.level<20)
633: console^=CON_ECHO_OFF;
634: break;
635: case '#': /* level 30 or higher */
636: if(useron.level<30)
637: console^=CON_ECHO_OFF;
638: break;
639: case '$': /* level 40 or higher */
640: if(useron.level<40)
641: console^=CON_ECHO_OFF;
642: break;
643: case '%': /* level 50 or higher */
644: if(useron.level<50)
645: console^=CON_ECHO_OFF;
646: break;
647: case '^': /* level 60 or higher */
648: if(useron.level<60)
649: console^=CON_ECHO_OFF;
650: break;
651: case '&': /* level 70 or higher */
652: if(useron.level<70)
653: console^=CON_ECHO_OFF;
654: break;
655: case '*': /* level 80 or higher */
656: if(useron.level<80)
657: console^=CON_ECHO_OFF;
658: break;
659: case '(': /* level 90 or higher */
660: if(useron.level<90)
661: console^=CON_ECHO_OFF;
662: break;
663: case ')': /* turn echo back on */
664: console&=~CON_ECHO_OFF;
665: break;
666: case '-': /* turn off all attributes if */
667: if(atr&(HIGH|BLINK|(LIGHTGRAY<<4))) /* high intensity, blink or */
668: attr(LIGHTGRAY); /* background bits are set */
669: break;
670: case '_': /* turn off all attributes if */
671: if(atr&(BLINK|(LIGHTGRAY<<4))) /* blink or background is set */
672: attr(LIGHTGRAY);
673: break;
674: case 'P': /* Pause */
675: pause();
676: break;
677: case 'Q': /* Pause reset */
678: lncntr=0;
679: break;
680: case 'T': /* Time */
681: now=time(NULL);
682: unixtodos(now,&date,&curtime);
683: bprintf("%02d:%02d %s"
684: ,curtime.ti_hour==0 ? 12
685: : curtime.ti_hour>12 ? curtime.ti_hour-12
686: : curtime.ti_hour, curtime.ti_min, curtime.ti_hour>11 ? "pm":"am");
687: break;
688: case 'D': /* Date */
689: now=time(NULL);
690: bputs(unixtodstr(now,tmp1));
691: break;
692: case ',': /* Delay 1/10 sec */
693: mswait(100);
694: break;
695: case ';': /* Delay 1/2 sec */
696: mswait(500);
697: break;
698: case '.': /* Delay 2 secs */
699: mswait(2000);
700: break;
701: case 'S': /* Synchronize */
702: ASYNC;
703: break;
704: case 'L': /* CLS (form feed) */
705: CLS;
706: break;
707: case '>': /* CLREOL */
708: if(useron.misc&ANSI)
709: bputs("\x1b[K");
710: else {
711: i=j=lclwx();
712: while(i++<79)
713: outchar(SP);
714: while(j++<79)
715: outchar(BS); }
716: break;
717: case '<': /* Non-destructive backspace */
718: outchar(BS);
719: break;
720: case '[': /* Carriage return */
721: outchar(CR);
722: break;
723: case ']': /* Line feed */
724: outchar(LF);
725: break;
726: case 'A': /* Ctrl-A */
727: outchar(1);
728: break;
729: case 'H': /* High intensity */
730: atr|=HIGH;
731: attr(atr);
732: break;
733: case 'I': /* Blink */
734: atr|=BLINK;
735: attr(atr);
736: break;
737: case 'N': /* Normal */
738: attr(LIGHTGRAY);
739: break;
740: case 'R':
741: atr=(atr&0xf8)|RED;
742: attr(atr);
743: break;
744: case 'G':
745: atr=(atr&0xf8)|GREEN;
746: attr(atr);
747: break;
748: case 'B':
749: atr=(atr&0xf8)|BLUE;
750: attr(atr);
751: break;
752: case 'W': /* White */
753: atr=(atr&0xf8)|LIGHTGRAY;
754: attr(atr);
755: break;
756: case 'C':
757: atr=(atr&0xf8)|CYAN;
758: attr(atr);
759: break;
760: case 'M':
761: atr=(atr&0xf8)|MAGENTA;
762: attr(atr);
763: break;
764: case 'Y': /* Yellow */
765: atr=(atr&0xf8)|BROWN;
766: attr(atr);
767: break;
768: case 'K': /* Black */
769: atr=(atr&0xf8)|BLACK;
770: attr(atr);
771: break;
772: case '0': /* Black Background */
773: atr=(atr&0x8f)|(BLACK<<4);
774: attr(atr);
775: break;
776: case '1': /* Red Background */
777: atr=(atr&0x8f)|(RED<<4);
778: attr(atr);
779: break;
780: case '2': /* Green Background */
781: atr=(atr&0x8f)|(GREEN<<4);
782: attr(atr);
783: break;
784: case '3': /* Yellow Background */
785: atr=(atr&0x8f)|(BROWN<<4);
786: attr(atr);
787: break;
788: case '4': /* Blue Background */
789: atr=(atr&0x8f)|(BLUE<<4);
790: attr(atr);
791: break;
792: case '5': /* Magenta Background */
793: atr=(atr&0x8f)|(MAGENTA<<4);
794: attr(atr);
795: break;
796: case '6': /* Cyan Background */
797: atr=(atr&0x8f)|(CYAN<<4);
798: attr(atr);
799: break;
800: case '7': /* White Background */
801: atr=(atr&0x8f)|(LIGHTGRAY<<4);
802: attr(atr);
803: break; }
804: }
805:
806: /***************************************************************************/
807: /* Changes local and remote text attributes accounting for monochrome */
808: /***************************************************************************/
809: /****************************************************************************/
810: /* Sends ansi codes to change remote ansi terminal's colors */
811: /* Only sends necessary codes - tracks remote terminal's current attributes */
812: /* through the 'curatr' variable */
813: /****************************************************************************/
814: void attr(int atr)
815: {
816:
817: if(!(useron.misc&ANSI))
818: return;
819: if(!(useron.misc&COLOR)) { /* eliminate colors if user doesn't have them */
820: if(atr&LIGHTGRAY) /* if any foreground bits set, set all */
821: atr|=LIGHTGRAY;
822: if(atr&(LIGHTGRAY<<4)) /* if any background bits set, set all */
823: atr|=(LIGHTGRAY<<4);
824: if(atr&LIGHTGRAY && atr&(LIGHTGRAY<<4))
825: atr&=~LIGHTGRAY; /* if background is solid, foreground is black */
826: if(!atr)
827: atr|=LIGHTGRAY; } /* don't allow black on black */
828: if(curatr==atr) /* text hasn't changed. don't send codes */
829: return;
830:
831: if((!(atr&HIGH) && curatr&HIGH) || (!(atr&BLINK) && curatr&BLINK)
832: || atr==LIGHTGRAY) {
833: bputs("\x1b[0m");
834: curatr=LIGHTGRAY; }
835:
836: if(atr==LIGHTGRAY) /* no attributes */
837: return;
838:
839: if(atr&BLINK) { /* special attributes */
840: if(!(curatr&BLINK))
841: bputs(ansi(BLINK)); }
842: if(atr&HIGH) {
843: if(!(curatr&HIGH))
844: bputs(ansi(HIGH)); }
845:
846: if((atr&0x7)==BLACK) { /* foreground colors */
847: if((curatr&0x7)!=BLACK)
848: bputs(ansi(BLACK)); }
849: else if((atr&0x7)==RED) {
850: if((curatr&0x7)!=RED)
851: bputs(ansi(RED)); }
852: else if((atr&0x7)==GREEN) {
853: if((curatr&0x7)!=GREEN)
854: bputs(ansi(GREEN)); }
855: else if((atr&0x7)==BROWN) {
856: if((curatr&0x7)!=BROWN)
857: bputs(ansi(BROWN)); }
858: else if((atr&0x7)==BLUE) {
859: if((curatr&0x7)!=BLUE)
860: bputs(ansi(BLUE)); }
861: else if((atr&0x7)==MAGENTA) {
862: if((curatr&0x7)!=MAGENTA)
863: bputs(ansi(MAGENTA)); }
864: else if((atr&0x7)==CYAN) {
865: if((curatr&0x7)!=CYAN)
866: bputs(ansi(CYAN)); }
867: else if((atr&0x7)==LIGHTGRAY) {
868: if((curatr&0x7)!=LIGHTGRAY)
869: bputs(ansi(LIGHTGRAY)); }
870:
871: if((atr&0x70)==(BLACK<<4)) { /* background colors */
872: if((curatr&0x70)!=(BLACK<<4))
873: bputs("\x1b[40m"); }
874: else if((atr&0x70)==(RED<<4)) {
875: if((curatr&0x70)!=(RED<<4))
876: bputs(ansi(RED<<4)); }
877: else if((atr&0x70)==(GREEN<<4)) {
878: if((curatr&0x70)!=(GREEN<<4))
879: bputs(ansi(GREEN<<4)); }
880: else if((atr&0x70)==(BROWN<<4)) {
881: if((curatr&0x70)!=(BROWN<<4))
882: bputs(ansi(BROWN<<4)); }
883: else if((atr&0x70)==(BLUE<<4)) {
884: if((curatr&0x70)!=(BLUE<<4))
885: bputs(ansi(BLUE<<4)); }
886: else if((atr&0x70)==(MAGENTA<<4)) {
887: if((curatr&0x70)!=(MAGENTA<<4))
888: bputs(ansi(MAGENTA<<4)); }
889: else if((atr&0x70)==(CYAN<<4)) {
890: if((curatr&0x70)!=(CYAN<<4))
891: bputs(ansi(CYAN<<4)); }
892: else if((atr&0x70)==(LIGHTGRAY<<4)) {
893: if((curatr&0x70)!=(LIGHTGRAY<<4))
894: bputs(ansi(LIGHTGRAY<<4)); }
895:
896: curatr=atr;
897: }
898:
899: /****************************************************************************/
900: /* Returns the ANSI code to obtain the value of atr. Mixed attributes */
901: /* high intensity colors, or background/forground cobinations don't work. */
902: /* A call to attr is more appropriate, being it is intelligent */
903: /****************************************************************************/
904: char *ansi(char atr)
905: {
906:
907: switch(atr) {
908: case (char)BLINK:
909: return("\x1b[5m");
910: case HIGH:
911: return("\x1b[1m");
912: case BLACK:
913: return("\x1b[30m");
914: case RED:
915: return("\x1b[31m");
916: case GREEN:
917: return("\x1b[32m");
918: case BROWN:
919: return("\x1b[33m");
920: case BLUE:
921: return("\x1b[34m");
922: case MAGENTA:
923: return("\x1b[35m");
924: case CYAN:
925: return("\x1b[36m");
926: case LIGHTGRAY:
927: return("\x1b[37m");
928: case (RED<<4):
929: return("\x1b[41m");
930: case (GREEN<<4):
931: return("\x1b[42m");
932: case (BROWN<<4):
933: return("\x1b[43m");
934: case (BLUE<<4):
935: return("\x1b[44m");
936: case (MAGENTA<<4):
937: return("\x1b[45m");
938: case (CYAN<<4):
939: return("\x1b[46m");
940: case (LIGHTGRAY<<4):
941: return("\x1b[47m"); }
942:
943: return("-Invalid use of ansi()-");
944: }
945:
946:
947: /****************************************************************************/
948: /* Checks to see if user has hit Pause or Abort. Returns 1 if user aborted. */
949: /* If the user hit Pause, waits for a key to be hit. */
950: /* Emulates remote XON/XOFF flow control on local console */
951: /* Preserves SS_ABORT flag state, if already set. */
952: /* Called from various listing procedures that wish to check for abort */
953: /****************************************************************************/
954: char msgabort()
955: {
956: char ch;
957:
958: if(sys_status&SS_SYSPAGE)
959: beep(random(800),1);
960: if(lkbrd(1)) {
961: ch=inkey(0);
962: if(sys_status&SS_ABORT) { /* ^c */
963: keybufbot=keybuftop=0;
964: return(1); }
965: else if(ch==17 && online==ON_REMOTE) /* ^q */
966: rioctl(IOCS|PAUSE);
967: else if(ch==19) /* ^s */
968: while(online) {
969: if((ch=inkey(0))!=0) {
970: if(ch==17) /* ^q */
971: return(0);
972: ungetkey(ch); }
973: if(sys_status&SS_ABORT) { /* ^c */
974: keybufbot=keybuftop=0;
975: return(1); }
976: checkline(); }
977: else if(ch)
978: ungetkey(ch); }
979: checkline();
980: if(sys_status&SS_ABORT)
981: return(1);
982: if(online==ON_REMOTE && rioctl(IOSTATE)&ABORT) {
983: rioctl(IOCS|ABORT);
984: sys_status|=SS_ABORT;
985: return(1); }
986: if(!online)
987: return(1);
988: return(0);
989: }
990:
991:
992: /****************************************************************************/
993: /* Takes the value 'sec' and makes a string the format HH:MM:SS */
994: /****************************************************************************/
995: char *sectostr(uint sec,char *str)
996: {
997: uchar hour,min,sec2;
998:
999: hour=(sec/60)/60;
1000: min=(sec/60)-(hour*60);
1001: sec2=sec-((min+(hour*60))*60);
1002: sprintf(str,"%2.2d:%2.2d:%2.2d",hour,min,sec2);
1003: return(str);
1004: }
1005:
1006:
1007: /****************************************************************************/
1008: /* Generates a 24 character ASCII string that represents the time_t pointer */
1009: /* Used as a replacement for ctime() */
1010: /****************************************************************************/
1011: char *timestr(time_t *intime)
1012: {
1013: static char str[256];
1014: char mer[3],hour;
1015: struct tm *gm;
1016:
1017: gm=localtime(intime);
1018: if(gm==NULL) {
1019: strcpy(str,"Invalid Time");
1020: return(str); }
1021: if(sys_misc&SM_MILITARY) {
1022: sprintf(str,"%s %s %02d %4d %02d:%02d:%02d"
1023: ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
1024: ,gm->tm_hour,gm->tm_min,gm->tm_sec);
1025: return(str); }
1026: if(gm->tm_hour>=12) {
1027: if(gm->tm_hour==12)
1028: hour=12;
1029: else
1030: hour=gm->tm_hour-12;
1031: strcpy(mer,"pm"); }
1032: else {
1033: if(gm->tm_hour==0)
1034: hour=12;
1035: else
1036: hour=gm->tm_hour;
1037: strcpy(mer,"am"); }
1038: sprintf(str,"%s %s %02d %4d %02d:%02d %s"
1039: ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
1040: ,hour,gm->tm_min,mer);
1041: return(str);
1042: }
1043:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.