1File: CONBDOS.C                                                           Page       1
     1    
     2   /********************************************************
     3   *							*
     4   *	CP/M-68K BDOS Character I/O Routines		*
     5   *							*
     6   *	This module does BDOS functions 1 thru 11	*
     7   *							*
     8   *	It contains the following functions which	*
     9   *	are called from the BDOS main routine:		*
    10   *		constat();				*
    11   *		conin();				*
    12   *		tabout();				*
    13   *		rawconio();				*
    14   *		prt_line();				*
    15   *		readline();				*
    16   *							*
    17   *	Copyright (c) 1982 Digital Research, Inc.	*
    18   *							*
    19   ********************************************************/
    20    
    21   #include "bdosinc.h"
    22    
    23   #include "bdosdef.h"
    24    
    25   #include "biosdef.h"
    26    
    27    
    28   #define   ctrlc  0x03
    29   #define   ctrle  0x05
    30   #define   ctrlp  0x10
    31   #define   ctrlq  0x11
    32   #define   ctrlr  0x12
    33   #define   ctrls  0x13
    34   #define   ctrlu  0x15
    35   #define   ctrlx  0x18
    36    
    37   #define   cr      0x0d
    38   #define   lf      0x0a
    39   #define   tab     0x09
    40   #define   rub     0x7f
    41   #define   bs      0x08
    42   #define   space   0x20
    43    
    44    
    45   EXTERN	warmboot();		/* External function definition */
    46    
    47    
    48   /******************/
    49   /* console status */
    50   /******************/
    51    
    52   BOOLEAN constat()
    53   {
    54       BSETUP
    55    
    56       return( GBL.kbchar ? TRUE : bconstat() );
    57   }
    58    
    59   /********************/
1File: CONBDOS.C                                                           Page       2
    60   /* check for ctrl/s */
    61   /* used internally  */
    62   /********************/
    63   conbrk()
    64   {
    65       REG UBYTE ch;
    66       REG BOOLEAN stop;
    67       BSETUP
    68    
    69       stop = FALSE;
    70       if ( bconstat() ) do
    71       {
    72   	if ( (ch = bconin()) == ctrlc ) warmboot(1);
    73   	if ( ch == ctrls ) stop = TRUE;
    74   	else if (ch == ctrlq) stop = FALSE;
    75   	else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
    76   	else 				/* Insert character in ring buffer  */
    77   	{				/*				    */
    78   	  if(GBL.kbchar < TBUFSIZ)	/* Room?			    */
    79   	  {				/************************************/
    80   	    *GBL.insptr++ = ch;		/* Yes, insert the character in buff*/
    81   	     GBL.kbchar++;		/* Up count			    */
    82   	  }				/************************************/
    83   	}				/* Note if no room, character is    */
    84   					/* Ignomiously discarded (!)	    */
    85   					/************************************/
    86       } while (stop);
    87   }
    88    
    89    
    90   /******************/
    91   /* console output */
    92   /* used internally*/
    93   /******************/
    94    
    95   conout(ch)
    96   REG UBYTE ch;
    97   {
    98       BSETUP
    99    
   100       conbrk();			/* check for control-s break */
   101       bconout(ch);		/* output character to console */
   102       if (GBL.lstecho) blstout(ch);	/* if ctrl-p on, echo to list dev */
   103       if (ch >= ' ') GBL.column++;	/* keep track of screen column */
   104       else if (ch == cr) GBL.column = 0;
   105       else if (ch == bs) GBL.column--;
   106   }
   107    
   108    
   109   /*************************************/
   110   /* console output with tab expansion */
   111   /*************************************/
   112    
   113   tabout(ch)
   114   REG UBYTE ch;		/* character to output to console	*/
   115   {
   116       BSETUP
   117    
   118       if (ch == tab) do
1File: CONBDOS.C                                                           Page       3
   119   	conout(' ');
   120       while (GBL.column & 7);
   121       else conout(ch);
   122   }
   123    
   124   /*******************************/
   125   /* console output with tab and */
   126   /* control character expansion */
   127   /*******************************/
   128    
   129   cookdout(ch)
   130   REG UBYTE ch;		/* character to output to console	*/
   131   {
   132       if (ch == tab) tabout(ch);	/* if tab, expand it	*/
   133       else
   134       {
   135   	if ( (UWORD)ch < (UWORD)' ' )
   136   	{
   137               conout( '^' );
   138   	    ch |= 0x40;
   139   	}
   140       conout(ch);			/* output the character */
   141       }
   142   }
   143    
   144    
   145   /*****************/
   146   /* console input */
   147   /*****************/
   148    
   149   UBYTE getch()		/* Get char from buffer or bios */
   150   			/* For internal use only	*/
   151   {
   152       REG UBYTE temp;
   153       BSETUP
   154   
   155       if(GBL.kbchar)
   156       {
   157   	temp = *GBL.remptr++;		/* Fetch the character    */
   158   	GBL.kbchar--;			/* Decrement the count	  */
   159   	if(!GBL.kbchar)			/* Gone to zero?	  */
   160   		GBL.remptr = GBL.insptr = &(GBL.t_buff[0]);
   161   	return(temp);
   162       }
   163       return( bconin() );			/* else get char from bios */
   164   }
   165    
   166   UBYTE conin()		/* BDOS console input function */
   167   {
   168       REG UBYTE ch;
   169       BSETUP
   170    
   171       conout( ch = getch() );
   172       if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
   173       return(ch);
   174   }
   175    
   176   /******************
   177   * raw console i/o *
1File: CONBDOS.C                                                           Page       4
   178   ******************/
   179    
   180   UBYTE rawconio(parm)	/* BDOS raw console I/O function */
   181    
   182   REG UWORD parm;
   183   {
   184       BSETUP
   185    
   186       if (parm == 0xff) return(getch());
   187       else if (parm == 0xfe) return(constat());
   188       else bconout(parm & 0xff);
   189   }
   190    
   191    
   192   /****************************************************/
   193   /* print line up to delimiter($) with tab expansion */
   194   /****************************************************/
   195    
   196   prt_line(p)
   197   REG UBYTE *p;
   198   {
   199       BSETUP
   200    
   201       while( *p != GBL.delim ) tabout( *p++ );
   202   }
   203    
   204    
   205   /**********************************************/
   206   /* read line with editing and bounds checking */
   207   /**********************************************/
   208    
   209   /* Two subroutines first */
   210    
   211   newline(startcol)
   212   REG UWORD startcol;
   213   {
   214       BSETUP
   215    
   216       conout(cr);			/* go to new line */
   217       conout(lf);
   218       while(startcol)
   219       {
   220   	conout(' ');
   221   	startcol -= 1;		/* start output at starting column */
   222       }
   223   }
   224    
   225    
   226   backsp(bufp, col)
   227   /* backspace one character position 	*/
   228   REG struct conbuf *bufp;	/* pointer to console buffer	*/
   229   REG WORD col;			/* starting console column	*/
   230   {
   231       REG UBYTE	ch;		/* current character		*/
   232       REG WORD 	i;
   233       REG UBYTE	*p;		/* character pointer		*/
   234       BSETUP
   235    
   236       if (bufp->retlen) --(bufp->retlen);
1File: CONBDOS.C                                                           Page       5
   237   				/* if buffer non-empty, decrease it by 1 */
   238       i = UBWORD(bufp->retlen);	/* get new character count	*/
   239       p = &(bufp->cbuf[0]);	/* point to character buffer	*/
   240       while (i--)			/* calculate column position 	*/
   241       {				/*  across entire char buffer	*/
   242   	ch = *p++;		/* get next char		*/
   243   	if ( ch == tab )
   244   	{
   245   	    col += 8;
   246   	    col &= ~7;		/* for tab, go to multiple of 8 */
   247   	}
   248   	else if ( (UWORD)ch < (UWORD)' ' ) col += 2;
   249   				/* control chars put out 2 printable chars */
   250   	else col += 1;
   251       }
   252       while (GBL.column > col)
   253       {
   254   	conout(bs);		/* backspace until we get to proper column */
   255   	conout(' ');
   256   	conout(bs);
   257       }
   258   }
   259    
   260    
   261   readline(p)			/* BDOS function 10 */
   262   REG struct conbuf *p;
   263   	
   264   {
   265       REG UBYTE ch;
   266       REG UWORD i;
   267       REG UWORD j;
   268       REG UBYTE *q;
   269       UWORD stcol;
   270    
   271       BSETUP
   272    
   273       stcol = GBL.column;		/* set up starting column */
   274       if (GBL.chainp != NULL)	/* chain to program code  */
   275       {
   276   	i = UBWORD(*(GBL.chainp++));
   277   	j = UBWORD(p->maxlen);
   278   	if (j < i) i = j;		/* don't overflow console buffer! */
   279   	p->retlen = (UBYTE)i;
   280   	q = p->cbuf;
   281   	while (i)
   282   	{
   283   	    cookdout( *q++ = *(GBL.chainp++) );
   284   	    i -= 1;
   285   	}
   286   	GBL.chainp = NULL;
   287   	return;
   288       }
   289    
   290       p->retlen = 0;		/* start out with empty buffer */
   291       while ( UBWORD(p->retlen) < UBWORD(p->maxlen) )
   292       {				/* main loop for read console buffer */
   293    
   294   	if ( ((ch=getch()) == ctrlc) && !(p->retlen) )
   295   	{
1File: CONBDOS.C                                                           Page       6
   296   	    cookdout(ctrlc);
   297   	    warmboot(1);
   298   	}
   299    
   300   	else if ( (ch == cr) || (ch == lf) )
   301   	{				/* if cr or lf, exit */
   302   	    conout(cr);
   303   	    break;
   304   	}
   305    
   306   	else if (ch == bs) backsp(p, stcol);	/* backspace */
   307    
   308   	else if (ch == rub)			/* delete character */
   309   	{
   310   	    if (GBL.echodel)
   311   	    {
   312   		if (p->retlen)
   313   		{
   314   		    i = UBWORD(--(p->retlen));
   315   		    conout( p->cbuf[i] );
   316   		}
   317   	    }
   318   	    else backsp(p, stcol);
   319   	}
   320    
   321   	else if (ch == ctrlp) GBL.lstecho = !GBL.lstecho;
   322   						/* control-p */
   323   	else if (ch == ctrlx)			/* control-x */
   324   	    do backsp(p,stcol); while (p->retlen);
   325    
   326   	else if (ch == ctrle) newline(stcol);	/* control-e */
   327    
   328   	else if (ch == ctrlu)			/* control-u */
   329   	{
   330   	    conout('#');
   331   	    newline(stcol);
   332   	    p->retlen = 0;
   333   	}
   334    
   335   	else if (ch == ctrlr)			/* control-r */
   336   	{
   337   	    conout('#');
   338   	    newline(stcol);
   339   	    for (i=0; i < UBWORD(p->retlen); i++)
   340   		    cookdout( p->cbuf[i] );
   341   	}
   342    
   343   	else					/* normal character */
   344   	    cookdout( p->cbuf[UBWORD((p->retlen)++)] = ch );
   345       }
   346   }
