home *** CD-ROM | disk | FTP | other *** search
- /********************************************************/
- /* Modul: SERV.C */
- /* enthält alle Funktionen, die nicht direkt von */
- /* außen erreichbar sind. */
- /********************************************************/
-
- #include <string.h>
- #include <stdlib.h>
- #include <conio.h>
- #include <dos.h>
- #include <alloc.h>
- #include "serv.h"
-
- extern char *cmdstr; /* siehe LOADER.C */
- extern struct text_info ti;
- extern windows *wptr;
- extern int *videoseg;
- extern unsigned *s_st,*s_st_top;
-
- int stmax; /* maximale Größe des Stackpuffers
- (in Byte!) */
- int xchgw[2000]; /* dient _wscroll() als temporärer
- Puffer */
-
- /* screen_init : screenstack initialisation
- legt die Adresse des Bildschirmadapters und des Stack-
- puffers fest und setzt den Stacktoppointer auf den An-
- fang des Puffers. */
- void screen_init ()
- {
- if (ti.currmode==7) /* Monochrome: Es wird angenommen,
- daß eine Herkuleskarte ange-
- schlossen ist. */
- {
- outportb(0x3BF,2); /* Dieser Befehl setzt die Herkules
- Karte in den sog. Full Mode, in
- dem beide Bildschirmseiten zur
- Verfügung stehen. Die 2. Seite
- wird als Stackpuffer genutzt.
- Falls jemand zwei Bildschirme
- an seinem Rechner angeschlossen
- hat z.B. MDA/HGC und CGA kann
- diese Zeile entfallen, wenn von
- der Monochrome-Konfiguration aus
- gestartet wird. Das Programm
- nutzt dann den Videospeicher der
- CGA-Karte als Puffer. */
- videoseg=(int *)0xB0000000L;
- s_st=(unsigned *)0xB8000000L;
- stmax=0x4000; /* (Größe der 2. Seite der Herku-
- les-Graphik-Karte: 32 kByte) */
- }
- else /* nicht Monochrome: CGA, EGA und
- VGA. Hier könnte wie oben ein
- freier Speicherbereich außerhalb
- des von der Textausgabe benutz-
- ten für für den Puffer einge-
- setzt werden. Zunächst wird hier
- wie für eine einzelne CGA-Karte
- erforderlich, dynamisch ein
- Puffer alloziert. */
- {
- videoseg=(int *)0xB8000000L;
- stmax=0x1000; /* da dynamisch alloziert werden
- habe ich hier einen kleineren
- Wert gewählt. Hier muß Speicher
- gespart werden. */
- s_st=(unsigned *)farmalloc((unsigned long)(stmax*2));
- }
- s_st_top=s_st;
- }
-
- /* getcurpos : get cursor position
- holt sich über den BIOS interrupt 10h die absolute Cur-
- sorposition */
- unsigned getcurpos (void)
- {
- _BH=0;
- _AH=3;
- geninterrupt(0x10);
- return(_DX);
- }
-
- /* setcurpos : set cursor position
- setzt über den BIOS interrupt 10h die Cursorposition.
- Der übergebene Parameter hat die Form 0xYYXX, so daß
- also der obere nibble (most significant byte, höchstwer-
- tiges Byte) die Zeile und das untere nibble entsprechend
- die Spalte definiert. Entsprechend ist auch die Übergabe
- bzw. Übernahme der Position vom BIOS definiert. Dies
- Format wird auch in getcurpos(), setwcurpos() und
- getwcurpos() benutzt. */
- void setcurpos (unsigned pos)
- {
- _BH=0;
- _DX=pos;
- _AH=2;
- geninterrupt(0x10);
- }
-
- /* getwcurpos : get window cursor position
- ermittelt die window relative Position des Cursors falls
- diese im Window liegt, sonst wird Position (0,0) zurück-
- gegeben. */
- unsigned getwcurpos (void)
- {
- int x,y;
- int frame=(wptr->fr_type!=0); /* frame wird hier 1 falls
- fr_type ungleich 1 ist,
- so daß ... */
- int ulx=wptr->ulx+frame; /* ... hier die beschreib-
- bare Window area */
- int uly=wptr->uly+frame; /* ermittelt werden kann.
- Diese Variablen */
- int lrx=wptr->lrx-frame; /* vermeiden eine wieder-
- holte umständliche */
- int lry=wptr->lry-frame; /* Berechnung der Variab-
- lenadressen. */
- x=getcurpos();
- y=x>>8;
- x=x&0xF;
- if (x>=ulx && y>=uly && x<=lrx && y<=lry)
- return(((y-uly)<<8)|(x-ulx));
- else
- return(0);
- }
-
- /* setwcurpos : set window cursor position
- setzt die neue Cursorposition nach relativen Windowkoor-
- dinaten, falls die Koordinaten im Window liegen */
- void setwcurpos (unsigned pos)
- {
- int x,y;
- int frame=(wptr->fr_type!=0);
- int ulx=wptr->ulx+frame;
- int uly=wptr->uly+frame;
- int lrx=wptr->lrx-frame;
- int lry=wptr->lry-frame;
- x=pos;
- y=x>>8;
- x=x&0xF;
- if (x<=lrx-ulx && y<=lry-uly)
- setcurpos(((y+uly)<<8)|(x+ulx));
- }
-
- /* getcurshape : get cursor shape
- ermittelt über BIOS interrupt 10h die aktuelle Cursor-
- form. Das Rückgabeformat enthält im oberen nibble (s.o.)
- die Startzeile für den Scan und im unteren die Endzei-
- le. */
- unsigned getcurshape (void)
- {
- _BH=0;
- _AH=3;
- geninterrupt(0x10);
- return(_CX);
- }
-
- /* setcurshape : set cursor shape
- setzt die gewünschte Cursorform. Zum Format siehe oben.
- Z.B. liefert bei der Mono-Karte mit einer Zeichenhöhe
- von 14 Zeile [0..13] die Startzeile 6 und Endzeile 6
- einen Bindestrich als Cursor: sh=0x0606. Mit (0,13)
- kann man einen Blockcursor erzeugen: sh=0x000C. Liegt
- die Startzeile außerhalb des maximalen Bereichs ist gar
- kein Cursor zu sehen: sh=0x0F00. Im Einzelfall sollte
- man hier aber die Dokumentation für die eigene Grafik-
- karte zu Rate ziehen. */
- void setcurshape (unsigned sh)
- {
- _CX=sh;
- _AH=1;
- geninterrupt(0x10);
- }
-
- /* _wscroll : window scroll (intern)
- führt das eigentliche shiften einer Zeile nach oben oder
- unten aus. */
- static void _wscroll (int dir)
- {
- int i;
- int frame=(wptr->fr_type!=0);
- int ulx=wptr->ulx+frame;
- int uly=wptr->uly+frame;
- int lrx=wptr->lrx-frame;
- int lry=wptr->lry-frame;
- if (!dir)
- {
- /* nach oben srollen */
- /* hole untere Zeile */
- gettext(ulx+1,uly+2,lrx+1,lry+1,xchgw);
- /* schreibe sie eine Zeile höher */
- puttext(ulx+1,uly+1,lrx+1,lry,xchgw);
- /* lösche untere Zeile */
- for(i=ulx;i<=lrx;i++)
- dispchar(' ',(int)i,(int)lry,wptr->attr);
- }
- else
- {
- /* nach unten scrollen */
- /* hole obere Zeile */
- gettext(ulx+1,uly+1,lrx+1,lry,xchgw);
- /* schreibe sie eine Zeile tiefer */
- puttext(ulx+1,uly+2,lrx+1,lry+1,xchgw);
- /* lösche obere Zeile */
- for(i=ulx;i<=lrx;i++)
- dispchar(' ',(int)i,(int)uly,wptr->attr);
- }
- }
-
- /* wscroll : window scroll
- führt einen scroll der Zeilen im aktiven Window um d
- Zeilen nach oben (d positiv) oder nach unten (d negativ)
- aus. */
- void wscroll (int d)
- {
- int i;
- if (d>0)
- {
- for(i=0;i<d;i++)
- _wscroll(0);
- }
- else
- {
- d=abs(d);
- for(i=0;i<d;i++)
- _wscroll(1);
- }
- }
-
- /* wclear : window clear
- löscht die beschreibare Fläche des aktiven Windows durch
- Vollschreiben mit Blanks der definierten Textfarbe des
- Windows. */
- void wclear (void)
- {
- int i;
- int frame=(wptr->fr_type!=0);
- int ulx=wptr->ulx+frame;
- int uly=wptr->uly+frame;
- int lrx=wptr->lrx-frame;
- int lry=wptr->lry-frame;
- int sym=' '|(wptr->attr<<8);
- for(i=ulx+uly*80;i<=lrx+lry*80;)
- {
- *(videoseg+i)=sym;
- if (i%80==lrx)
- i=((i/80)+1)*80+ulx;
- else
- i++;
- }
- }
-
- /* putccw : put char controlled in window
- setzt an der aktuellen Cursorposition ein Zeichen und
- setzt den Cursor auf den nächsten legalen Platz im
- Window, notfalls wird ein Scroll durchgeführt. Die Zei-
- chen werden zusätzlich auf Sonderfunktionen geprüft.
- Folgende Zeichen lösen keine direkte
- Zeichenausgabe aus:
- '\f' (0x0F) dez. 15 (Form Feed): scrolled das ganze
- Window hoch und po-
- sitioniert den Cur-
- sor auf (0,0) rela-
- tiv.
- '\t' (0x09) dez 9 (Tabulator): schreibt Blanks bis
- zur nächsten durch
- 8 teilbaren relati-
- ven Spaltenposi-
- tion.
- '\n' (0x0A) dez 10 (New Line): führt einen Zeilen-
- vorschub und (!) da
- nach einen Wagen-
- rücklauf (Carriage
- Return) aus.
- '\r' (0x0C) dez 13 (Return): Wagenrücklauf, po-
- sitioniert den
- Cursor am linken
- Rand ses Windows.
- '\a' (0x07) dez 7 (Audible Bell): Piepser
- '\b' (0x08) dez 8 (Backspace): geht ein Zechen
- nach links zurück
- ohne das Zeichen
- zu löschen. */
- int putccw (char c)
- {
- unsigned x,y,i;
- int frame=(wptr->fr_type!=0);
- int ulx=wptr->ulx+frame;
- int uly=wptr->uly+frame;
- int lrx=wptr->lrx-frame;
- int lry=wptr->lry-frame;
- int attr=wptr->attr;
- x=getcurpos(); /* um ein Hin- und Hertransformie-
- ren der Koordinaten zu vermei-*/
- y=x>>8; /* den, wird mit absoluten Werten*/
- x&=0xFF; /* gerechnet. */
- switch (c)
- {
- case '\f' :
- for (i=uly;i<=lry;i++)
- _wscroll(0);
- x=ulx;
- y=lry;
- setcurpos((y<<8)|x);
- break;
- case '\t' :
- if (x+(8-(x-ulx)%8)<lrx)
- {
- while (((x-ulx)%8!=0)&&((x-lrx)%8!=0))
- {
- putccw(' '); /* Whow! Rekursiv! */
- x++;
- }
- break;
- }
- case '\n' :
- if (y<lry)
- {
- if (x<lrx)
- setcurpos(((++y)<<8)|(++x));
- else
- setcurpos(((++y)<<8)|ulx);
- }
- else
- {
- _wscroll(0);
- if (x<lrx)
- setcurpos((y<<8)|(++x));
- else
- setcurpos((y<<8)|ulx);
- } /* Das fehlende break bewirkt, daß auch
- noch der return ausgeführt wird */
- case '\r' :
- setcurpos((y<<8)|ulx);
- break;
- case '\a' :
- sound(440); /* Kammerton a */
- delay(20);
- nosound();
- break;
- case '\b' :
- if (x>ulx)
- setcurpos((y<<8)|(x-1));
- else
- if (y>uly)
- setcurpos(((y-1)<<8)|lrx);
- break;
- default : /* Der Normalfall. Zeichenausgabe */
- dispchar(c,x,y,attr);
- if (x<lrx)
- {
- setcurpos((y<<8)|(x+1));
- }
- else
- if (y<lry)
- {
- setcurpos(((y+1)<<8)|ulx);
- }
- else
- {
- _wscroll(0);
- setcurpos((y<<8)|ulx);
- }
- }
- return(c);
- }
-
- /* dispstr : display string
- Stringausgabe window relativ, allerdings (!) ohne die
- Begrenzung des Windows zu beachten. Dient der schnellen
- Stringausgabe. Kontrolle der Ausgabe wird bei wputs()
- durchgeführt. */
- int dispstr (const char *str, int cy, int cx, int attr)
- {
- int i,len=strlen(str);
- int frame=(wptr->fr_type!=0);
- int x=wptr->ulx+frame+cx;
- int y=wptr->uly+frame+cy;
- for(i=0;i<len;i++)
- dispchar(*(str+i),x+i,y,attr);
- return(*(str+i));
- }
-
- /* wputs : window put string
- kontrollierte Ausgabe von Strings im aktiven Window */
- int wputs (const char *str)
- {
- int i,len=strlen(str);
- for(i=0;i<len;i++)
- putccw(*(str+i));
- return(*(str+i));
- }
-
- /* ccmdstr : clear commandstring (and set a)
- löscht cmdstr (schreibt mit Blanks voll) und schreibt in
- die erste Stelle die Ziffer (!) a. */
- void ccmdstr (int a, char *cmdstr)
- {
- int i;
- cmdstr[0]=a+48;
- for(i=1;cmdstr[i]!=0;i++)
- cmdstr[i]=' ';
- }
-
- /* wopen : window open
- öffnet ein Window mit den angegebenen Koordinaten ulx,
- uly, lrx, lry schreibt den zu sichernden Bereich in den
- Puffer wbptr, löscht den Windowbereich mit dem Attribut
- attr, zeichnet einen Rahmen der Art fr_type mit der
- Farbe fr_attr und trägt eventuell einen Header in der
- Rahmenfarbe zentriert ein. */
- void wopen (unsigned *wbptr, int ulx, int uly, int lrx,
- int lry, int attr, int fr_type, int fr_attr,
- char *header)
- {
- int i,j,frame=(fr_type!=0);
- char ulc,urc,llc,lrc,hor,ver;
- int hlen=strlen(header);
- wptr->ulx=ulx;
- wptr->uly=uly;
- wptr->lrx=lrx;
- wptr->lry=lry;
- wptr->attr=attr;
- wptr->fr_type=fr_type;
- wptr->fr_attr=fr_attr;
- wptr->header=header;
- /* sichere zu überschreibenden Bereich des Windows */
- gettext(ulx+1,uly+1,lrx+1,lry+1,wbptr);
- if (fr_type) /* wenn Rahmen gewünscht ... */
- {
- switch (fr_type) /* definiere Rahmenformen */
- {
- case 2 :
- ulc='╔';
- urc='╗';
- llc='╚';
- lrc='╝';
- hor='═';
- ver='║';
- break;
- case 3 :
- ulc='╓';
- urc='╖';
- llc='╙';
- lrc='╜';
- hor='─';
- ver='║';
- break;
- case 4 :
- ulc='╒';
- urc='╕';
- llc='╘';
- lrc='╛';
- hor='═';
- ver='│';
- break;
- case 5 :
- ulc='█';
- urc='█';
- llc='█';
- lrc='█';
- hor='█';
- ver='█';
- break;
- default :
- ulc='┌';
- urc='┐';
- llc='└';
- lrc='┘';
- hor='─';
- ver='│';
- break;
- }
- dispchar(ulc,ulx,uly,fr_attr); /* zeichne den Rahmen */
- dispchar(urc,lrx,uly,fr_attr);
- dispchar(llc,ulx,lry,fr_attr);
- dispchar(lrc,lrx,lry,fr_attr);
- for (i=ulx+1;i<lrx;i++)
- {
- dispchar(hor,i,uly,fr_attr);
- dispchar(hor,i,lry,fr_attr);
- }
- for (i=uly+1;i<lry;i++)
- {
- dispchar(ver,ulx,i,fr_attr);
- dispchar(ver,lrx,i,fr_attr);
- }
- if (*header!=0) /* wenn Header gewünscht ... */
- {
- i=(lrx-ulx)/2-hlen/2+ulx; /* zentriere */
- if (i<ulx)
- i=ulx;
- if (i>ulx)
- dispchar(' ',i-1,uly,fr_attr); /* zuerst ein Blank */
- /* dann Header */
- for(j=0;i<lrx&&*(header+j);i++,j++)
- dispchar(*(header+j),i,uly,fr_attr);
- if (i<=lrx)
- dispchar(' ',i,uly,fr_attr); /* ein Blank anhängen */
- }
- }
- wclear();
- /* setze Cursor auf (0,0) relativ */
- setcurpos(((uly+frame)<<8)|(ulx+frame));
- }
-
- /* attr_string : attribute string (to attribute value)
- wandelt den in dBASE/FoxBASE übergebenen Farbcode in
- einen integer Wert um. Die Funktion wird von der Funk-
- tion screenh() genutzt um ein Window zu öffnen, dessen
- Farbcodes in dem Format übergeben werden, wie es für die
- Anweisung SET COLOR TO üblich ist. Zum Beispiel: +B/W
- (hellblau auf weiß) = 0111 1001 b = 0x79 (nachrech-
- nen). */
- int attr_string (char *attrs)
- {
- int i,attr=0,backflag=0;
- for(i=0;i<3 && *(attrs+i)!=0;i++)
- switch (*(attrs+i))
- {
- case '*' :
- attr|=0x80<<(backflag*4);
- break;
- case '+' :
- attr|=0x08<<(backflag*4);
- break;
- case 'x' :
- case 'X' :
- break;
- case 'w' :
- case 'W' :
- attr|=0x07<<(backflag*4);
- break;
- case 'i' :
- case 'I' :
- attr|=0x70<<(backflag*4);
- break;
- case 'u' :
- case 'U' :
- attr|=0x01<<(backflag*4);
- break;
- case 'n' :
- case 'N' :
- attr|=0x00<<(backflag*4);
- break;
- case 'b' :
- case 'B' :
- attr|=0x01<<(backflag*4);
- break;
- case 'g' :
- case 'G' :
- attr|=0x02<<(backflag*4);
- break;
- case 'r' :
- case 'R' :
- attr|=0x04<<(backflag*4);
- break;
- case '/' :
- backflag=1;
- break;
- }
- return(attr);
- }