/********************************************************************* * * TITLE: DMOUTIL * * DATE: 10-05-90 * * ABSTRACT: This module contains utility functions for the demo * program for the DOSRMX Real Time Extensions. * * * MODIFIED: * ***********************************************************************/ /* * INTEL CORPORATION PROPRIETARY INFORMATION * * This software is supplied under the terms of a * license agreement or nondisclosure agreement with * Intel Corporation and may not be copied or disclosed * except in accordance with the terms of that agreement. * */ #ifdef DOS #include #endif #include #include #include #include #include #include "jobnames.h" #ifdef DOS #include "rwdosrte.h" #include #endif #define TRUE 0xff #define FALSE 0x0 #define FOUND 0x0 #define MYJOB 1 #define ROOTJOB 3 #define INFINITE 0xffff #define NOWAITING 0x0 #define ReadOnlyShare 1 #define GetTermChars 4 #define SetTermChars 5 #define MaskEditBits 0xfdfc #define SetNoEditMode 0x0201 #define VDUPARAMSIZE 36 #define ZeroBuffers 0 #define SizeOfName 4 #define ScreenSize 25 #define zeroaddr 0 #define onemegalias 0x100000 #define HIGHWORD 0xffff0000 #define LOWWORD 0x0000ffff /* get object literals */ #define MAXNOOBJS 20 #define fifoobjmbx 0 #define fifodatmbx 0x20 #define fifo 0 #define zerounits 0 #define maxtenunits 10 #define objmailboxtype 1 #define datmailboxtype 2 #define descriptortype 3 #define semaphoretype 4 #define segmenttype 6 /* rmx types returned by rqgettype */ #define rmxjobtype 1 #define rmxtasktype 2 #define rmxmbxtype 3 #define rmxsemtype 4 #define rmxregtype 5 #define rmxsegtype 6 #define rmxexttype 7 /* VDU control string literals to index control structure */ #define AFES 0 #define AFER 1 #define AFEK 2 #define AFEL 3 #define AFMB 4 #define AFML 5 #define AFMR 6 #define AFMU 7 #define AFMD 8 #define AFMH 9 #define ControlMax 10 typedef struct rmxstring { BYTE numb_char; char string[128]; } RMXSTRING; typedef struct pointer { TOKEN segment; WORD offset; } POINTER; /* list of object names created */ RMXSTRING list_of_names[MAXNOOBJS]; #ifdef RMX /* VDU parameters and control sequences */ RMXSTRING control[ControlMax]; TERMATTRIBSTRUCT vdu_param; TOKEN vdu_connection; TOKEN vdu_read_mbx; static char * ControlName[ControlMax] = {"AFES","AFER","AFEK","AFEL","AFMB", "AFML","AFMR","AFMU","AFMD","AFMH"}; #endif TOKEN root_job; /* used to catalogue my job in for the other prog to find */ TOKEN my_job; /* Used to catalogue objects against */ static char * create_error[7] = { " ", /* object type 0 invalid */ "Exception creating object mailbox", "Exception creating data mailbox", "Exception creating a descriptor", " ", /* object type 5 invalid */ "Exception creating a segment"}; static BYTE rq_global_strg[] = {8,"RQGLOBAL"}; static BYTE rcrt_strg[] = {5,"R?CRT"}; static BYTE termcapfile[] = {15,":CONFIG:TERMCAP"}; static BYTE CI[] = {4,":CI:"}; static char name[] = "NAME"; static char error_exists_wrong_type[] = "ERROR - object is the incorrect type\n"; static char obj_list_full[] = "ERROR - no more space available in object list\n"; static char error_invalid_type[] = "ERROR - invalid object type, not supported\n"; static char error_invalid_objdir[] = "ERROR - invalid job token for object dir\n"; static char nul_message[] = {0}; static char LF = 0x0a; static char CR = 0x0d; static char VT = 0x0b; int debug_char2; #ifdef RMX /* ** RQEREADSEGMENT - copies pvam mode data to real mode space */ void rqereadsegment(TOKEN pvam_seg, DWORD pvam_offset, DWORD realmode_ptr, WORD size, WORD far * except_ptr) { TOKEN realmodeseg; void * dest_ptr; void * source_ptr; union { void near * offset; DWORD realaddr; } buildoffset; realmodeseg = rqecreatedescriptor(zeroaddr, onemegalias, except_ptr); if (*except_ptr == EOK) { buildoffset.realaddr = (((realmode_ptr & HIGHWORD) >> 12) + (realmode_ptr & LOWWORD)); dest_ptr = buildptr(realmodeseg,buildoffset.offset); buildoffset.realaddr = pvam_offset; source_ptr = buildptr(pvam_seg,buildoffset.offset); memcpy(dest_ptr,source_ptr,size); rqedeletedescriptor(realmodeseg,except_ptr); } } /* ** RQEWRITESEGMENT - copies real mode data to pvam mode segment */ void rqewritesegment(DWORD realmode_ptr, TOKEN pvam_seg, DWORD pvam_offset, WORD size, WORD far * except_ptr) { TOKEN realmodeseg; void * dest_ptr; void * source_ptr; union { void near * offset; DWORD realaddr; } buildoffset; realmodeseg = rqecreatedescriptor(zeroaddr, onemegalias, except_ptr); if (*except_ptr == EOK) { buildoffset.realaddr = (((realmode_ptr & HIGHWORD) >> 12) + (realmode_ptr & LOWWORD)); source_ptr = buildptr(realmodeseg,buildoffset.offset); buildoffset.realaddr = pvam_offset; dest_ptr = buildptr(pvam_seg,buildoffset.offset); memcpy(dest_ptr,source_ptr,size); rqedeletedescriptor(realmodeseg,except_ptr); } } #endif /* ** CHECKSEG - checks the memory pointed to for a valid RMXSTRING */ BYTE checkseg(TOKEN seg_tkn, DWORD segsize) { RMXSTRING name; BYTE count; WORD except; #ifdef DOS rqereadsegment(seg_tkn,(DWORD)0,&name,(WORD)(segsize < 129 ? segsize : 129),&except); #else memcpy(&name,buildptr(seg_tkn,0),(segsize < 129 ? segsize : 129)); except = EOK; #endif if ((except == EOK) && ( name.numb_char <= 128) && ( name.numb_char <= (segsize - 2)) && (name.string[name.numb_char] == 0)) { for ( count = 0; (count < name.numb_char) && ((isprint(name.string[count]) != 0) || (name.string[count] == '?')); count++) ; if (count == name.numb_char) return TRUE; } return FALSE; } /* ** ADD_TO_LIST - adds the rmx name to a list used to remove delete the objects ** created by this job when it terminates. */ void add_to_list(RMXSTRING far * namptr, WORD far * exptr) { WORD index; for ( index = 0; ((index < MAXNOOBJS) && (list_of_names[index].numb_char != 0)); index++) ; if ( index < MAXNOOBJS ) { memcpy(list_of_names[index].string,namptr->string,namptr->numb_char); list_of_names[index].numb_char = namptr->numb_char; *exptr = EOK; } else *exptr = ESPACE; } /* ** REMOVE_FROM_LIST - removes an rmx name from the list of names */ void remove_from_list(RMXSTRING far * namptr) { WORD index; WORD rindex; index = 0; while ( (index < MAXNOOBJS) && ((list_of_names[index].numb_char != namptr->numb_char) || (memcmp(list_of_names[index].string, namptr->string, namptr->numb_char) != 0))) index++; if (index < MAXNOOBJS) { /* ** found a match, need to remove from list by copying last entry ** over the matched entry and deleting the last entry */ for (rindex = 0; ((rindex < MAXNOOBJS) && (list_of_names[rindex].numb_char != 0)); rindex++ ) ; rindex--; /* point to last entry */ memcpy( list_of_names[index].string, list_of_names[rindex].string, list_of_names[rindex].numb_char ); list_of_names[index].numb_char = list_of_names[rindex].numb_char; list_of_names[rindex].numb_char = 0; } } /****************************************************************** * * TITLE: REMOVE_MY_NAME * * CALLING SEQUENCE: remove_my_name(); * * INTERFACE VARIABLES: NONE * * PARAMETERS: * * GLOBAL VARIABLES: * * * ABSTRACT: This function uncatalogues the program name from the * root job. * ******************************************************************/ void remove_my_name() { WORD except; #ifdef DOS rquncatalogobject(root_job,myjobname,&except); #else rquncatalogobject(root_job,(char *)myjobname,&except); #endif } /* ** READ_CAT_NAME - reads a ten character name from the keyboard */ BYTE read_cat_name(char far * msg_ptr,char name[]) { BYTE name_complete; BYTE i; name_complete = FALSE; while (name_complete == FALSE) { printf("%s",msg_ptr); i = 0; while(((i < 10) && (name[i] = getchar()) !='\n')) i++; if (i < 10) { name[i] = 0; /* null terminate the string */ for(i = 0; ((isprint(name[i]) != 0) || (name[i] != 0)); i++) name[i] = toupper(name[i]); if (name[i] == 0) name_complete = TRUE; else { printf("\nERROR - Only Alphanumeric characters\n"); printf("Press ENTER to continue :-"); while((name[i] = getchar()) !='\n') ; } } else { while((name[i] = getchar()) !='\n') ; printf("\nERROR - name too long, only 10 characters max\n"); printf("Press ENTER to continue :-"); while((name[i] = getchar()) !='\n') ; } } return i; } /* ** DELETE_OBJECT - deletes object passed to it */ void delete_object(WORD objecttype, TOKEN object, WORD far * exptr) { switch(objecttype) { case objmailboxtype: case datmailboxtype: rqdeletemailbox(object,exptr); break; case semaphoretype: rqdeletesemaphore(object,exptr); break; case descriptortype: rqedeletedescriptor(object,exptr); break; case segmenttype: rqdeletesegment(object,exptr); break; default: error_message(error_invalid_type); *exptr = ETYPE; break; } } /* ** DELETE_RMX_OBJECT - deletes object passed to it */ void delete_RMX_object(WORD rmxtype, TOKEN object, WORD far * exptr) { switch(rmxtype) { case rmxmbxtype: rqdeletemailbox(object,exptr); break; case rmxsemtype: rqdeletesemaphore(object,exptr); break; case rmxsegtype: rqdeletesegment(object,exptr); break; default: error_message(error_invalid_type); *exptr = ETYPE; break; } } /* ** FIND_NAMED_OBJECT - looks for the object token in the two possible ** job object directories. */ TOKEN find_named_object(RMXSTRING far * namptr,TOKEN far * job_tkn_ptr,WORD far * exptr) { TOKEN job_tkn; int count; TOKEN temp_tkn; /* see if the object exist in the other jobs directory first */ #ifdef DOS job_tkn = rqlookupobject(root_job,otherjobname, 0, exptr); #else job_tkn = rqlookupobject(root_job,(char *)otherjobname, 0, exptr); #endif if (*exptr == EOK) count = 2; /* two loops */ else { count = 1; /* only one loop, no other job only our job */ job_tkn = my_job; } while (count > 0) { temp_tkn = rqlookupobject(job_tkn, (BYTE far * )namptr,(WORD)0, exptr); if (*exptr == EOK) { *job_tkn_ptr = job_tkn; return temp_tkn; } else { job_tkn = my_job; count--; } } return 0; } /****************************************************************** * * TITLE: REMOVE_ALL_OBJECTS * * CALLING SEQUENCE: remove_all_objects(); * * INTERFACE VARIABLES: NONE * * PARAMETERS: * * GLOBAL VARIABLES: * * * ABSTRACT: This function deletes all objects created by this * program. * ******************************************************************/ void remove_all_objects() { WORD index; TOKEN del_tkn; WORD rmx_type; WORD except; for (index = 0; ((index < MAXNOOBJS) && (list_of_names[index].numb_char != 0)); index++) { del_tkn = rqlookupobject(my_job,(BYTE far * )&list_of_names[index], NOWAITING,&except); if (except == EOK) { /* object exists, uncatalog it and delete it */ rquncatalogobject(my_job,(BYTE far * )&list_of_names[index],&except); rmx_type = rqgettype(del_tkn,&except); if (except == EOK) delete_rmx_object(rmx_type,del_tkn,&except); } } } /* ** REMOVE_OBJECT - deletes a named object that is catalogued in one on ** the job object directories. */ void remove_object(RMXSTRING far * namptr) { TOKEN obj_tkn; TOKEN job_tkn; WORD rmx_type; WORD except; remove_from_list(namptr); obj_tkn = find_named_object(namptr,&job_tkn,&except); if (except == EOK) /* name found */ { rquncatalogobject(job_tkn,(BYTE far * )namptr,&except); /* remove from obj dir */ rmx_type = rqgettype(obj_tkn,&except); /* find type */ delete_rmx_object(rmx_type,obj_tkn,&except); } } /* ** CREATE_OBJECT - creates a requested object */ TOKEN create_object(void far * p, WORD far * exptr) { TOKEN temp_tkn; struct { WORD objecttype; TOKEN objdir; RMXSTRING name; } far * param_p; struct { WORD objecttype; TOKEN objdir; RMXSTRING name; DWORD absaddr; DWORD segsize; } far * descrip_p; struct { WORD objecttype; TOKEN objdir; RMXSTRING name; DWORD segsize; } far * segment_p; WORD except; param_p = p; /* setup parameter pointers */ descrip_p = p; segment_p = p; add_to_list(¶m_p->name,exptr); if (*exptr == EOK) { switch(param_p->objecttype) { case objmailboxtype: temp_tkn = rqcreatemailbox(fifoobjmbx,exptr); break; case datmailboxtype: temp_tkn = rqcreatemailbox(fifodatmbx,exptr); break; case semaphoretype: temp_tkn = rqcreatesemaphore(zerounits, maxtenunits, fifo, exptr); break; case descriptortype: temp_tkn = rqecreatedescriptor(descrip_p->absaddr, descrip_p->segsize, exptr); break; case segmenttype: temp_tkn = rqcreatesegment(segment_p->segsize, exptr); break; default: error_message(error_invalid_type); remove_from_list(¶m_p->name); *exptr = ETYPE; break; } /* catalogue the object */ if (*exptr == EOK) rqcatalogobject ( param_p->objdir, temp_tkn, (BYTE far * )¶m_p->name, exptr); else { printf("%04XH %s",*exptr,create_error[param_p->objecttype]); error_message(nul_message); /* wait for CR, no message */ } if (*exptr == EOK) return temp_tkn; else { delete_object(param_p->objecttype,temp_tkn,&except); remove_from_list(¶m_p->name); error_message(error_invalid_objdir); return 0; } } else return 0; } /* ** CHECK_TYPE - checks that the two types are equal */ WORD check_type(WORD type, WORD req_type) { if (((req_type == objmailboxtype) || (req_type == datmailboxtype)) && (type == rmxmbxtype)) return EOK; else if (((req_type == descriptortype) || (req_type == segmenttype)) && (type == rmxsegtype)) return EOK; else if (((req_type == semaphoretype)) && (type == rmxsemtype)) return EOK; else return ETYPE; } /* ** GET_RMX_OBJECT - creates the desired object and returns the token */ TOKEN get_rmx_object(void far * p, WORD far * exptr) { int count; TOKEN temp_tkn; WORD type; struct { WORD objecttype; TOKEN objdir; RMXSTRING name; } far * param_p; param_p = p; /* setup parameter pointers */ temp_tkn = find_named_object(¶m_p->name,¶m_p->objdir,exptr); if (*exptr == EOK) { type = rqgettype(temp_tkn,exptr); if (*exptr == EOK) { if (check_type(type,param_p->objecttype) == EOK) return temp_tkn; else { error_message(error_exists_wrong_type); *exptr = ETYPE; /* name exists but type wrong */ return 0; } } else return 0; } return 0; } #ifdef RMX /****************************************************************** * * TITLE: GETCHE * * CALLING SEQUENCE: getche(); * * INTERFACE VARIABLES: NONE * * PARAMETERS: * * GLOBAL VARIABLES: * * * ABSTRACT: This function emulates the getche function of microsoft * C for the RMX version of the program. * ******************************************************************/ int getche() { int character; DWORD actual; WORD except; character = 0; rqaread(vdu_connection,&character,1,vdu_read_mbx,&except); if (except == EOK) { actual = rqwaitio(vdu_connection,vdu_read_mbx,INFINITE,&except); if ((except == EOK) && (actual == 1)) { debug_char2 = character; return character; } else return 0; } else return 0; } #endif /* ** displays the memory on the screen */ void display_memory(TOKEN pvam_seg, DWORD pvam_offset,DWORD segsize) { BYTE i; BYTE j; BYTE mp[160]; unsigned count; DWORD mem_offset; DWORD mem_count; DWORD display_count; DWORD offset_addr; WORD except; WORD objtype; char again; printf("\n\n"); again = 'Y'; mem_count = 0; mem_offset = pvam_offset; while (again != 'q' && again != 'Q' && mem_count != segsize) { display_count = (segsize-mem_count)<=160?(segsize-mem_count):160; objtype = rqgettype(pvam_seg,&except); /* check if stil there */ if (except == EOK) { #ifdef DOS rqereadsegment(pvam_seg,mem_offset,mp,display_count,&except); if (except !=EOK) { printf("\n\nException %04XH from rqereadsegment in display_memory\n\n",except); } #else memcpy(&mp[0],buildptr(pvam_seg,(void near * )mem_offset),display_count); #endif for (count = 0; ((count < 10) && (mem_count != segsize)); count ++) { offset_addr = (mem_offset + (count*16)); #ifdef DOS printf("%04X:%08XH ",pvam_seg,offset_addr); #else printf("%04X:%08XH ",((WORD)pvam_seg),offset_addr); #endif for (i=0; ((i < 16) && (mem_count != segsize)); i++) { printf("%02X ",mp[i+(count * 16)]); mem_count++; } j = i; for (i; i < 16; i++) printf(" "); for (i=0; ((i < 16) && (i < j)); i++) { if ((mp[i+(count * 16)] > 0x1f) && (mp[i+(count * 16)] < 0x7f)) printf("%c",mp[i+(count * 16)]); else printf("."); } printf("\n"); } mem_offset += display_count; printf("Enter Q or q to quit, any other key to continue :- "); again = getche(); printf("\n"); } else { printf("\n\nERROR The segment no longer exists\n"); error_message(nul_message); again = 'Q'; } } } #ifdef RMX /* ** Sets up the vdu control data structure from the data passed to it */ void setup_control_struc(char far * vdu_data) { int index; WORD count; DWORD control_sequence; BYTE far * ptr; for (index = 0; index < ControlMax; index++) { count = 0; /* find the control sequence in the buffer */ while ( (strncmp(ControlName[index], &vdu_data[count], (strlen(ControlName[index]))) != FOUND) && (strncmp("//",&vdu_data[count],2) != FOUND)) count++; if (strncmp("//",&vdu_data[count],2) != FOUND) { /* Found the control sequence extract it and save */ count += strlen(ControlName[index]); /* point to after control name */ ptr = (BYTE far *)&vdu_data[count]; count = 0; while ((isalnum(ptr[count]) == 0) && (ptr[count] != ';')) count++; if (ptr[count] == ';') control[index].numb_char = 0; /* Not present */ else if (isalnum(ptr[count]) != 0) { ptr = &ptr[count]; count = 0; control_sequence = 0; for (count = 0; ptr[count] != ';'; count++) { if (isalpha(ptr[count]) != 0) control_sequence = (control_sequence * 0x10) + (ptr[count] - 0x37); else control_sequence = (control_sequence * 0x10) + (ptr[count] - 0x30); } count = (count/2) + (count%2); /* number of characters */ control[index].numb_char = count; while (count > 0) { control[index].string[count - 1] = (control_sequence >> ((control[index].numb_char - count)*8)) & 0x000000ff; count--; } } else { /* ASCII control string to copy to control string */ ptr = &ptr[count]; count = 0; while (ptr[count] != ';') { control[index].string[count] = ptr[count]; } } } else control[index].numb_char = 0; /* Not present */ } } #endif /****************************************************************** * * TITLE: INITIALISATION * * CALLING SEQUENCE: initialisation(); * * INTERFACE VARIABLES: NONE * * PARAMETERS: * * GLOBAL VARIABLES: * * * ABSTRACT: This function provides the initialisation of the * program. * ******************************************************************/ void initialisation() { TOKEN hi_job; TOKEN rq_global; TOKEN terminal_type; TOKEN termcap; TOKEN buffer_seg; char far * charptr; RMXSTRING far * ptr; DWORD bytes_read; #ifdef RMX char far * term_ptr; SFILESTATUSSTRUCT term_info; TERMATTRIBSTRUCT vdu_output_param; BOOLEAN VduFound; #endif WORD count; WORD oldexcept; WORD except; /* Set up the video control data structure */ root_job = rqgettasktokens(ROOTJOB, &except); if (except != EOK) exit(except); my_job = rqgettasktokens(MYJOB, &except); #ifdef RMX if (except == EOK) { hi_job = rqlookupobject(my_job, (BYTE far * )rq_global_strg, INFINITE, &except); } else exit(except); /* setup vdu connection */ vdu_connection = rqsattachfile(&CI, &except); if (except != EOK) exit(except); rqsopen(vdu_connection, ReadOnlyShare, ZeroBuffers, &except); if (except != EOK) exit(except); rqsspecial(vdu_connection, GetTermChars, &vdu_output_param, 0, &except); if (except != EOK) exit(except); vdu_read_mbx = rqcreatemailbox(fifoobjmbx,&except); if (except != EOK) exit(except); memcpy(&vdu_param, &vdu_output_param, VDUPARAMSIZE); /* save */ vdu_output_param.connectionflags = (vdu_output_param.connectionflags & MaskEditBits) | SetNoEditMode; rqsspecial(vdu_connection, SetTermChars, &vdu_output_param, 0, &except); if (except != EOK) exit(except); /* Find the HI job, this is where RQGLOBAL points to itself */ if (except == EOK) { rq_global = rqlookupobject(hi_job, &rq_global_strg, INFINITE, &except); } else exit(except); if (except == EOK) { while (rq_global != hi_job) { hi_job = rq_global; rq_global = rqlookupobject(hi_job, &rq_global_strg, INFINITE, &except); if (except != EOK) exit(except); } } else exit(except); /* Found the HI JOB, now lookup the terminal token R?CRT */ terminal_type = rqlookupobject(hi_job, &rcrt_strg, INFINITE, &except); if (except != EOK) exit(except); /* found R?CRT token, extract the terminal type. */ ptr = buildptr(terminal_type,0); termcap = rqsattachfile(&termcapfile,&except); if (except != EOK) exit(except); rqsgetfilestatus(&termcapfile,&term_info,&except); if (except != EOK) exit(except); rqsopen(termcap,ReadOnlyShare,ZeroBuffers,&except); if (except != EOK) { oldexcept = except; rqsdeleteconnection(termcap,&except); exit(oldexcept); } buffer_seg = rqcreatesegment((term_info.filesize + 1),&except); if (except != EOK) exit(except); charptr = buildptr(buffer_seg,0); bytes_read = rqsreadmove(termcap,charptr,term_info.filesize,&except); if ((except != EOK) || (bytes_read != term_info.filesize)) { /* ERROR reading file */ if (except != EOK) oldexcept = except; else oldexcept = ESPACE; /* not all read */ rqsclose(termcap,&except); rqsdeleteconnection(termcap,&except); exit(oldexcept); } /* finished with the file, close it */ rqsclose(termcap,&except); rqsdeleteconnection(termcap,&except); ptr->string[ptr->numb_char] = 0; /* null the end of the string */ charptr[term_info.filesize] = 0; /* null the end of the string */ /* make sure all chars are upper case */ for(count = 0;charptr[count] != 0; count++) charptr[count] = toupper(charptr[count]); for(count = 0;ptr->string[count] != 0; count++) ptr->string[count] = toupper(ptr->string[count]); term_ptr = charptr; VduFound = FALSE; while (VduFound == FALSE) { term_ptr = strstr(term_ptr,&name[0]); if (term_ptr == NULL) exit(ESUPPORT); /* if end of file exit */ term_ptr = &term_ptr[SizeOfName]; /* point to end of 'NAME' */ count = 0; /* Find the start of the VDU name */ while (isalnum(term_ptr[count]) == 0) count++; term_ptr = &term_ptr[count]; /* point to VDU name */ if (strncmp(ptr->string,term_ptr,ptr->numb_char) == FOUND) VduFound = TRUE; } /* found the terminal type, now initialise the structure */ count = 0; while (term_ptr[count] != ';') /* find start of control sequences */ count++; setup_control_struc(&term_ptr[count]); /* setup the data structure */ #endif for ( count = 0; count < MAXNOOBJS; count++) /* clear list of object names */ list_of_names[count].numb_char = 0; #ifdef DOS rqcatalogobject(root_job,my_job,myjobname,&except); #else rqcatalogobject(root_job,my_job,(char *)myjobname,&except); #endif if (except != EOK) exit(except); } /****************************************************************** * * TITLE: CLEAR_SCREEN * * CALLING SEQUENCE: clear_screen(); * * INTERFACE VARIABLES: NONE * * PARAMETERS: * * GLOBAL VARIABLES: * * * ABSTRACT: This function clears the screen. * ******************************************************************/ void clear_screen() { BYTE count; /* Clear the screen */ #ifdef RMX if (control[AFES].numb_char > 0) { for (count = 0; count < control[AFES].numb_char; count++) putchar(control[AFES].string[count]); } else { putchar(CR); for (count = 0; count < ScreenSize; count++) putchar(LF); } /* Cursor home */ if (control[AFMB].numb_char > 0) { for (count = 0; count < control[AFMB].numb_char; count++) putchar(control[AFMB].string[count]); } else { for (count = 0; count < ScreenSize; count++) putchar(VT); } #else _clearscreen(_GCLEARSCREEN); #endif }