/***************************************************************************** Gestionnaire de terminal Unix: printf.c (c) Pierre ADRIAANS 1994 *****************************************************************************/ #include "printf.h" int Printf(char *Format,...) { int LS,CS, /* Fenetre active d'affichage */ LI,CI, HT,LN, CursY,CursX, /* Position actuelle du curseur */ NbPut = 0, /* Nombre de caracteres affiches (linefeed, carriage return et bell compris). Code de retour de la fonction */ ToPrint = 0, /* Nombre de caracteres a reellement afficher */ LineFeeds = 0, /* Nombre de linefeeds a imprimer */ Reste, /* Nombre de caracteres encore disponibles dans la fenetre active */ RowsToPrint, /* Nombre de lignes de la fenetre active a imprimer */ RowsLeft, /* Nombre de lignes encore disponibles dans la fenetre active */ DeltaRows, /* Difference des deux precedents */ src, /* Nbre de caracteres ajoutes par sprintf() */ Offset, /* Offset dans la memoire video */ CptFormat = 0, /* Offset dans la chaine argument */ CptBuf = 0; /* Offset dans la chaine de formattage */ char Attr, /* Attribut d'affichage courant */ ch, /* Caractere a afficher */ FormatStr[10], /* Chaine de format pour sprintf */ TempStr[2], /* Chaine Temporaire pour strcat */ *FormatBuffer = (char *)NULL, /* Buffer de formattage des arguments */ *TmpBuf = (char *)NULL; /* Buffer d'impression de sprintf() */ VideoEle_t *VM; /* Memoire video */ /* variables de recuperation des arguments */ int i,j; unsigned u; char c; double d; char *s; int *pi; void *p; va_list ap; /* pointeur d'argument dans la pile */ /* Premiere partie: impression dans FormatBuffer par sprintf. Tous les formats sont recuperes un a un et passes a sprintf. L'impression commence au debut du buffer, et un offset suit le nombre de caracteres renvoye par sprintf ou place dans le buffer chaque fois. Toutes les options de format sont supportees. */ FormatBuffer = (char *)malloc(PRINTF_BUF_SIZE); if(FormatBuffer == (char *)NULL) raise(SIGME); FormatBuffer[0] = 0; TmpBuf = (char *)malloc(PRINTF_BUF_SIZE); if(TmpBuf == (char *)NULL) raise(SIGME); TmpBuf[0] = 0; va_start(ap,Format); /* Initialisation sur le seul parametre fixe */ while((Format[CptFormat] != 0) && (CptBuf < PRINTF_BUF_SIZE)) { if(Format[CptFormat] != '%') /* Afficher le caractere */ { switch(Format[CptFormat]) { case '\n': FormatBuffer[CptBuf] = LF; CptBuf++; FormatBuffer[CptBuf] = CR; CptBuf++; FormatBuffer[CptBuf] = 0; CptFormat++; LineFeeds++; break; case '\r': FormatBuffer[CptBuf] = CR; CptBuf++; CptFormat++; FormatBuffer[CptBuf] = 0; break; case '\t': /* Conversion du TAB en espaces: il faut aligner sur des multiples de PRINTF_TAB_SIZE */ j = PRINTF_TAB_SIZE - (CptBuf % PRINTF_TAB_SIZE); for(i=0;i 0 && DeltaRows < HT && HT > 3) { ScrollUpWin(LS,CS,HT,LN,DeltaRows); CursY -= DeltaRows; GotoXY(CursY,CursX); } while((ch = FormatBuffer[NbPut]) != 0) { switch(ch) { case BELL: putchar(BELL); NbPut++; break; case LF: if(CursY == LI) ScrollUpWin(LS,CS,HT,LN,1); else { CursY++; GotoXY(CursY,CursX); } NbPut++; break; case CR: CursX = CS; GotoXY(CursY,CursX); if(FormatBuffer[NbPut - 1] == LF) fflush(stdout); NbPut++; break; default: if(isdisplay(ch)) { PutToScr(ch); Offset = VidMemOffset(CursY,CursX); VM[Offset].Code = ch; VM[Offset].Attr = Attr; CursX++; SetXY(CursY,CursX); if(CursX > CI) { CursX = CS; if(CursY == LI) ScrollUpWin(LS,CS,HT,LN,1); else CursY++; GotoXY(CursY,CursX); } } NbPut++; } } free(FormatBuffer); free(TmpBuf); UnlockKbd(); return(NbPut); }