/* * head.h * ***************************************************************************** * * Dynamic Heading for C Programs * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ***************************************************************************** * * Author : Rajesh _ThE gReAt * Built on : Tuesday,January 21, 2002, 9:59:31 AM * Last Modified on : Friday, February 08, 2002, 3:27:40 PM * * Known errors : Since the fuction load() captures timer interrupt * it must be used with caution. * Also , the first argument to load is modified if * it contains newlines or TABS. * ***************************************************************************** * DISCLAIMER: ***************************************************************************** * * Programmers may incorporate any or all code into their programs, * giving proper credit within the source. Publication of the * source routines is permitted so long as proper credit is given * to Rajesh _ThE gReAt. * * Copyright (C) 2002, 2003 by Rajesh _ThE gReAt. You may use this program, or * code or tables extracted from it, as desired without restriction. * I can not and will not be held responsible for any damage caused from * the use of this software. * * Read license.txt from http://www.rajeshgoli.com/license.txt * or http://www.rajeshgoli.com/license.htm * before using / distributing / or any sort of use of my source * Also read my disclaimer http://www.rajeshgoli.com/disclaimer.htm * * YOU AGREE TO BE BOUND BY MY DISCLAIMER AND LICENSE BY IN ANY WAY * USING THIS FILE . * ***************************************************************************** * This source works with Turbo C 2.0 and Turbo C++ 3.0 and above. ***************************************************************************** * Rajesh _ThE gReAt is a synonym of Rajesh Goli * Source freely distributable *****************************************************************************/ /* For testing the header file */ /* #define TEST_HEAD_H */ /* Make this 1 if you want the interrupt our_timer to put the message chars too on VDU memory . Best leave it alone , it is not desirable .. Use loadtext() instead */ #define PUT_MSG_TOO 0 /* The VDU memory has the following structure for colors Bbbbffff in each byte where B is blink bit bbb are backgound color bits ffff are foreground color bits This macro sets it */ #define our_attrb(attrb,fattrb,battrb,blink) \ (attrb) &= 0x00; \ (attrb) |= ((fattrb) & 0x0F) ; \ (attrb) |= (((battrb)<<4) & 0x70) ; \ (attrb) |= (((blink)<<7) & ~0x7F); typedef unsigned char byte; #ifndef __HEAD_H #define __HEAD_H #endif #ifndef __DOS_H #include #endif /* Returned vaules by load() if an error occurs */ /* The x and/or y values are not valid */ #define X_Y_ERROR -1 /* A string is already being highlighted */ #define LOADED_ERROR -2 /* Attributes supplied are invalid */ #define ATTRB_ERROR -3 /* First location of VDU memory */ byte far *scr = (byte far *)0xB0008000; #if( PUT_MSG_TOO == 1) char *message; #endif unsigned len,clk,cnt,wait_for; byte hcolor,normcolor; short loaded = 0; /* Function ( or poiner to function ) prototypes */ int load(char *,byte ,byte ,byte ,unsigned ,unsigned short ,unsigned short ); void unload( void ); int chkattrb(byte ); unsigned conv(float ,short ); void loadtext(const char *msg); void changeattr(byte ,byte ,byte ,short ); void interrupt (*prev_0x08)(); void interrupt our_timer(); /* This function can be called only once during the execution , unless there is a call to unload (); */ /* msg = string to be displayed , No NewLines or TABS allowed first instance of Newline or TAB found is replaced by '\0' attrb = color of text ( normal ) hattrb = color of text ( highlighted ) battrb = The color of background of char (normal) wait_cnt = 1 means 1/18.2 part of a second 2 means 2/18.2 part of a second It specifies the period during which a char remains highlighted x = x co-ordinate of starting postion of string y = y co-ordinate of starting postion of string */ int load(char *msg,byte attrb,byte hattrb,byte battrb,unsigned wait_cnt,unsigned short x,unsigned short y) { int i; /* A message is already loaded , timer is already captured once another capture might lead to its slowdown and also system instability , so prevent it*/ if(loaded == 1) return LOADED_ERROR; /* Find NewLine , if any replace it by NULL */ for(i = 0; msg[i] && msg[i] != '\n';i++); if(msg[i] == '\n' || msg[i] == '\t') msg[i] = 0; /* Find out lenght of string including the terminating NULL */ i = 0; while(msg[i++]); len = i - 1; /* -1 to remove the trailing NULL */ /* If we are given illegal x or y or we are given x such that we cannot accomodate string within a single line then return error code */ if(x< 1 || x > (80 - len + 1) || y < 1 || y > 25) return X_Y_ERROR; /* If we are given illegal attributes then return error code */ if(chkattrb(attrb) || chkattrb(hattrb) || chkattrb(battrb)) return ATTRB_ERROR; /* Make the pointer point to first location where the string is to be written */ scr += ( ((x-1)*2) + ((y-1)*2*80) ); /* Set the colors */ our_attrb(normcolor,attrb,battrb,0); our_attrb(hcolor,hattrb,battrb,0); /* Copy the string to VDU memory */ for(i = 0 ; msg[i] ; i++) { *(scr+(i*2)) = msg[i]; *(scr+(i*2)+1) = normcolor; } /* If the message is some how lost say by printing newlines by other parts of program then this will come to rescue it will print the string again Though this is not very desirable use loadtext() instead . */ #if( PUT_MSG_TOO == 1) message = msg; #endif /* Initialise the variables needed by our_timer() */ clk = 0; cnt = 0; wait_for = wait_cnt; /* Store previous interrupt */ prev_0x08 = getvect(0x08); /* Put our timer to work */ setvect(0x08,our_timer); /* Flag variable to prevent calling load more than once */ loaded = 1; return 1; } short active = 0 ,on = 0; /* Call this b4 calling load() again or b4 exiting the program to clean up */ void unload() { if(loaded != 1) return; /* Set back the previous timer */ setvect(0x08,prev_0x08); /* If some char is still highlighted make it normal */ if(on) { *(scr + cnt*2 + 1) = normcolor; } /* Flag reset */ loaded = 0; return; } /* DO NOT EDIT THIS FUNCTION UNLESS YOU KNOW WHAT YOU ARE DOING I CANNOT BE HELD RESPONSIBLE FOR ANY PROBLEM CAUSED BY USING AND/OR MODIFING THIS FUNCTION */ void interrupt our_timer() { /* We've waited long enough */ if(clk == wait_for) { /* If this is already active , no point in using this */ if(!active) { /* Flag to indicate that this portion is active */ active = 1; /* Some char is highlighted */ if(on) { on = 0; #if( PUT_MSG_TOO == 1 ) *(scr + cnt*2) = message[cnt]; #endif /* Reset the highlighted char */ *(scr + cnt*2 + 1) = normcolor; /* Point to next char of string */ cnt++; /* reset flag */ active = 0; /* This HAS to be called anyway ... */ (*prev_0x08)() ; /* End the present call */ return; } /* too long ;) */ if(cnt == len) cnt = 0; #if( PUT_MSG_TOO == 1 ) *(scr + cnt*2) = message[cnt]; #endif /* Highlight msg[cnt] */ *(scr + cnt*2 + 1) = hcolor; /* Tell the program a char is highlighted */ on = 1; /* reset flag */ active = 0; /* start a fresh count */ clk = 0; } /* The part is already active is wait_for too short? Anyway reset clock , begin a new count */ else clk = 0; } /* We havent waited long enough */ else clk++; /* This HAS to be called anyway ... */ (*prev_0x08)(); } /* Function to check weather the provided attributes are valid */ int chkattrb(byte attrb) { if(attrb > 15) return 1; else return 0; } #define SEC 1 #define mSEC 2 /* A fuction to convert seconds or milliseconds to the type of unit required by load() how_may = how many secs or millisecs what_type = SEC or mSEC */ unsigned conv(float how_many,short what_type) { float tim_sec; if(how_many <= 0) return 0; if(what_type != SEC && what_type != mSEC) return 0; if(what_type == SEC) { tim_sec = how_many; tim_sec *= 18.2; if(tim_sec >= 0 && tim_sec <= 1) return 1; else { if(tim_sec - (float)(int)(tim_sec) < 0.5) return ((unsigned)tim_sec); else return ((unsigned)tim_sec + 1); } } if(what_type == mSEC) { tim_sec = how_many; tim_sec /= 1000; /* convert to Secs */ tim_sec *= 18.2; if(tim_sec >= 0 && tim_sec <= 1) return 1; else { if(tim_sec - (float)(int)(tim_sec) < 0.5) return ((unsigned)tim_sec); else return ((unsigned)tim_sec + 1); } } } /* If u clrscr() once when load is active, instead of unload()ing and load()ing again , use this . */ void loadtext(const char *msg) { int i; /* load() is not called yet! */ if(loaded != 1) return; /* Copy the string to VDU memory */ for(i = 0 ; msg[i] ; i++) { *(scr+(i*2)) = msg[i]; *(scr+(i*2)+1) = normcolor; } return; } /* change attributes of message while load() is still active usefull if u want the chars to blink , there is no option for this in load() */ void changeattr(byte fore,byte hlgt,byte bak,short blink) { our_attrb(normcolor,fore,bak,blink); our_attrb(hcolor,hlgt,bak,blink); return; } #ifdef TEST_HEAD_H #include #include /* This is for checking */ void main() { clrscr(); load("http://www.rajeshgoli.com",GREEN,LIGHTGREEN,BLACK,3,80/2-strlen("http://www.rajeshgoli.com")/2,2); gotoxy(10,10); while(!kbhit()); getch(); unload(); printf("\nHit a key ..."); getch(); clrscr(); } #endif