Nickolay.info. Алгоритмы. Пишем на Си функции нижнего уровня

Ниже приводится листинг, содержащий несколько десятков стандартных и нестандартных функций Си. Главная программа только тестирует функции, причем не все. Внимательный анализ листинга и комментариев поможет извлечь немало полезной при изучении языка информации.

#include <stdio.h>
         /* нужна только для printf в демо*/
//////////////////////////////////////////////////Прототипы
#define MODE unsigned char
#define YES 0x01
#define NO  0x00
#define UP_DIR 0
#define DOWN_DIR 1
        //Форматы даты:
#define MDY  0
#define MDYY 1
#define DMY  2
#define DMYY 3
#define YMD  4
#define YYMD 5
#define YDM  6
#define YYDM 7
        //Клавиши
#define ENTER 0x1C0D
#define LEFT  0x4B00
#define RIGHT 0x4D00
#define UP    0x4800
#define DOWN  0x5000
#define ESC   0x011B
#define PAGE_UP 0x4900
#define PAGE_DO 0x5100
#define HOME    0x4700
#define END     0x4F00

#define BUF_LEN 4000             /* Длина буфера для сохранения экрана */
MODE Buffer[BUF_LEN],            /* Буфер для сохранения экрана */
     String[129],                /* Строка для разбора */
     Var[129];                   /* Строка окружения */
unsigned BufPos=0;
MODE SetString=NO;               // Флаг записи в окружение
MODE WEEKDAY,DAY,MON,HOUR,MIN,SEC, //Дата и время
     HIGHDOS,LOWDOS;               //Версия DOS
int YEAR;
MODE DateFormat=MDY, FullFormat=YES,  //
     DateDividor='/',TimeDividor=':'; //Разделители даты и времени
MODE ATTR=0x07;                       //Атрибут экрана
MODE Col=7,Bk=0;                      //Цвет и фон экрана
MODE Explode=NO, Shadow=NO, Border=0x02,
     Filler=' ', Break=YES, ScrollDir=DOWN_DIR;
MODE MaxCol=80, MaxRow=25,           //Размеры экрана
     Saver=YES;                      //Флаг сохранения экрана
MODE RowCursor=0,ColCursor=0,        //Позиция курсора
     LogDrives=3;                    //Количество дисков
MODE X1=0,Y1=0,X2=24,Y2=39,
     UNS=1,
     Arg=0,*Args[24],
     Return=0,Byte=0;
static MODE **ArgsPtr=&Args[0];
void Exit (MODE);

MODE FULL=0,
     ON=1,
     SetEnv=0;

#define MONO_VIDEO 3
#define COLOR_VIDEO80 2
#define COLOR_VIDEO40 1

MODE IsSoprocessor, KolFlops, ActiveVideo, KolPrinters; //HardStatus()
unsigned BaseMemorySize; //HardStatus()

union LONG {
 int High,Low;
 long Long;
} L;

unsigned strlen_(MODE *);
void ClearBox (MODE x1, MODE y1, MODE x2,MODE y2,MODE attr);
void DrawBox (MODE x1, MODE y1, MODE x2, MODE y2, MODE Type, MODE Fill);
void SetCursor (MODE Row, MODE Col);
void WriteString (MODE *s,MODE attr);
void WritePosString (MODE x,MODE y,MODE *Str,MODE attr);
void Save (MODE,MODE,MODE,MODE);
void Restore (MODE,MODE,MODE,MODE);
MODE GetPopup (MODE x1, MODE y1, MODE kol, MODE **Str,MODE Saver);
MODE GetMenu (MODE x1, MODE y1, MODE kol, MODE **Str,MODE Saver);
int Get_Key(void);


//////////////////////////////////////////////////Работа со строками:
unsigned char UpCase (unsigned char c) {
 if (c>96 && c<123 || c>159 && c<176) c-=32; // a-z, а-п
 else if (c>223 && c<240) c-=80; // р-я
 return c;
}

void UpCaseStr (unsigned char *Str) {
 unsigned char c; unsigned i;
 for (i=0; ; i++) {
  c=*(Str+i);
  if (c==0) break;
  c=UpCase (c);
  *(Str+i)=c;
 }
 return;
}

int StrCmp (unsigned char *s1, unsigned char *s2, unsigned maxlen) {
 //Если maxlen=0, сравнивает как stricmp() - до конца строк,
 //иначе как strnicmp()
 int j=0; unsigned char c1,c2;
 while (1) {
  c1=UpCase(*(s1+j)); c2=UpCase(*(s2+j));
  if(c1=='\0' || c2=='\0' || (maxlen!=0 && j==maxlen)) break;
  if (c1==c2) j++;
  else break;
 }
 if (c1<c2) j=c2-c1;
 else if (c1>c2) j=c1-c2;
 else j=0;
 return j;
}

unsigned char *StrChr (unsigned char *s, unsigned char c) {
 while (*s) {
  if (*s==c) return s;
  s++;
 }
 return 0;
}

unsigned char *StrRChr (unsigned char *s, unsigned char c) {
 unsigned char *p=0;
 while (*s) {
  if (*s==c) p=s;
  s++;
 }
 return p;
}

unsigned char *StrTok (unsigned char *s, unsigned char *c) {
 //Указатель на первый символ s, не содержащийся в c
 unsigned char *Ptr;
 unsigned j;
 for (j=0; *(s+j); j++) {
  Ptr=StrChr (c,*(s+j));
  if (!Ptr) return (s+j);
 }
 return 0;
}

void StrSet (unsigned char *s, unsigned char c, unsigned kol) {
 //Устанавливает в kol байт строки s значение c
 unsigned u;
 for (u=0; u<kol; u++) *(s+u)=c;
}

unsigned char IsDigit (unsigned char c) {
 if (c>47 && c<58 ) return (1);
 return (0);
}

unsigned char IsSpace(unsigned char c) {
 if ((c>0x08 && c<0x0e) || c==0x20) return 1;
 return 0;
}

unsigned char IsUnsigned (unsigned char *ptr) {
 // Проверяет, является ли строка записью целого беззнакового числа
 // Возвращает 0 или 1
 unsigned char Ret=1;
 while (*ptr==' ' || *ptr=='\t') ptr++;
 if (*ptr=='\0') return 0;
 for (; *ptr; ptr++) if (!IsDigit(*ptr)) { Ret=0; break; }
 return Ret;
}

unsigned AtoU (unsigned char *s) {
 unsigned n;
 for (; IsSpace(*s); s++);
 for (n=0;IsDigit(*s);s++) n=10*n+*s-'0';
 return n;
}

unsigned StrLen (unsigned char *s) {
 unsigned l=0;
 while (*s!='\0') { l++; s++; }
 return l;
}

void StrRev (unsigned char *s) {
 int c; unsigned char *t;
 for (t=s+StrLen(s)-1; s<t; s++,t--) {
  c=*s; *s=*t; *t=c;
 }
}

void UtoA (unsigned n, unsigned char *s) {
 unsigned char *t=s;
 do {  *s++=n%10+'0'; } while ((n/=10)!=0);
 *s='\0';
 StrRev (t);
}

unsigned char *StrCat (unsigned char *d, unsigned char *s) {
 unsigned char *ret=d;
 while (*d) d++;
 while (*s) *d++=*s++;
 *d='\0';
 return ret;
}

void StrCpy (unsigned char *d, unsigned char *s) {
 while (*s) *d++=*s++;
 *d='\0';
}

////////////////////////////////// Клавиатура и экран
int Get_Key (void) {
 asm mov ax,0;
 asm int 16h;
 return _AX;
}

void WritePosString (unsigned char x,unsigned char y,unsigned char *Str,unsigned char attr) {
 SetCursor (x, y);
 WriteString (Str,attr);
}

unsigned char RevAttr (unsigned char Attr) {
 return ((Attr&0x70)>>4)|((Attr<<4)&0x7F);
}

unsigned char GetPopup (unsigned char x1, unsigned char y1, unsigned char kol, unsigned char **Str,unsigned char Saver) {
 // Падающее меню; возвращает номер выбора (с 1) или 0 по нажатию ESC
 int sim;
 unsigned char x2,y2,i,maxlen=0,cursor=0,rev=RevAttr (ATTR);
 for (i=0; i<kol; i++) {
  sim=StrLen(Str[i]);
  if (sim>maxlen) maxlen=sim;
 }
 x2=x1+1+kol; y2=y1+1+maxlen;
 if (Saver) Save (x1,y1,x2,y2);
 ClearBox (x1,y1,x2,y2,ATTR);
 DrawBox (x1,y1,x2,y2,0x02,0);
 x1++; y1++;
 for (i=0; i<kol; i++) WritePosString (x1+i,y1,Str[i],ATTR);
 kol--;
 while (1) {
  WritePosString (x1+cursor,y1,Str[cursor],rev);
  SetCursor (x1+cursor, y1);
  sim=Get_Key();
  WriteString (Str[cursor],ATTR);
  switch (sim) {
   case ESC: cursor=0;  goto OUT;
   case ENTER: cursor++; goto OUT;
   case UP:
    if (cursor>0) cursor--;
    else cursor=kol;
   break;
   case DOWN:
    if (cursor<kol) cursor++;
    else cursor=0;
   break;
   case PAGE_UP: cursor=0; break;
   case PAGE_DO: cursor=kol; break;
  }
 }
OUT:
 x1--; y1--;
 if (Saver) Restore (x1,y1,x2,y2);
 return (cursor);
}

unsigned char GetMenu (unsigned char x1, unsigned char y1, unsigned char kol, unsigned char **Str,unsigned char Saver) {
 //Горизонтальное меню; возвращает номер выбора (с 1) или 0 по нажатию ESC
 int sim;
 unsigned char x2,y2,i,maxlen=0,cursor=0,rev=RevAttr (ATTR);
 for (i=0; i<kol; i++) {
  sim=StrLen(Str[i]);
  maxlen+=(sim+1);
 }
 y2=y1+maxlen;
 if (Saver) Save (x1,y1,x1,y2);
 ClearBox (x1,y1,x1,y2,ATTR);
 y1++;
 for (i=0,maxlen=0; i<kol; i++) {
  WritePosString (x1,y1+maxlen,Str[i],ATTR);
  maxlen+=(StrLen(Str[i])+1);
 }
 kol--; y2=y1;
 while (1) {
  WritePosString (x1,y2,Str[cursor],rev);
  SetCursor (x1, y2);
  sim=Get_Key();
  WriteString (Str[cursor],ATTR);
  switch (sim) {
   case ESC: cursor=0;
    for (i=0; i<=kol; i++) y2+=(StrLen(Str[i])+1);
    y1--;
    if (Saver) Save (x1,y1,x1,y2);
   goto OUT;
   case ENTER: cursor++; goto OUT;
   case LEFT:
    if (cursor>0) cursor--;
    else cursor=kol;
   break;
   case RIGHT:
    if (cursor<kol) cursor++;
    else cursor=0;
   break;
   case HOME: cursor=0; break;
   case END: cursor=kol; break;
  }
  y2=y1;
  for (i=0; i<cursor; i++) y2+=(StrLen(Str[i])+1);
 }
OUT:
 for (i=0; i<=kol; i++) y2+=(StrLen(Str[i])+1);
 y1--;
 if (Saver) Restore (x1,y1,x1,y2);
 return (cursor);
}

////////////////////////////////Тестирование оборудования:

unsigned char PrinterIsReady (unsigned Printer) {
 // Проверяет готовность принтера и возвращает 0 OK или 1 ERROR
 // Printer=0,1,2 - LPT1/2/3
 asm mov ah,2;
 asm mov dx,Printer;
 asm int 17h;
 asm cmp ah,090h; //Не занято и выбрано
 asm je OK;
 asm cmp ah,010h;
 asm je OK;
 return 0x01;
OK: return 0x00;
}

unsigned char DriveReady (unsigned char Drive) {
//    Выдает стандартную ошибку DOS
 asm mov ah,36h;
 asm mov dl,Drive; //0-текущий,1-A,2-B и т.д.
 asm int 21h;
 if (_AX==0xffff) return NO;
 return YES;
}

void HardStatus (void) {
 //Параметры BIOS
 unsigned char H,L;
 asm int 11h;
 H=_AH; L=_AL;
 IsSoprocessor=L&0x02 ? YES: NO;
 KolFlops=(L&0x01 ? (((L&0xC0)>>6)+1) : 0);
 ActiveVideo=(L&0x30)>>4;
 KolPrinters=(H&0xC0)>>6;
 asm int 12h;
 BaseMemorySize=_AX;
 return;
}

unsigned char GetDrive (void) {
 //0-A,1-B,...
 asm mov ah,19h;
 asm int 21h;
 return _AL;
}

unsigned char SetDrive (unsigned char Disk) {
 //Disk=0 -A,1 -B, ...
 //Вернет число логических дисков или LASTDRIVE - что больше
 asm mov ah,0eh;
 asm mov dl,Disk;
 asm int 21h;
 return _AL;
}

unsigned char GetDirectory (unsigned char Drive) {
 //0-OK,1-ERROR, Путь в Buffer
 //Путь не начинается с \ и имени диска
 //0-текщий,1-A,2-B,3-C,...
 asm mov ax,seg Buffer;
 asm mov ds,ax;
 asm mov si,offset Buffer;
 asm mov ah,47h;
 asm mov dl,Drive;
 asm int 21h;
 asm jnc OK;
 return 1;
OK: return 0;
}

unsigned long DiskSpace (unsigned char Drive, unsigned char FreeOnly) {
 //Если FreeOnly вернет информацию о свободном месте
 unsigned long Volume;
 unsigned SecPerClast, FreeClast, BytesPerSec, ClastPerDrive;
 asm {
  mov ah,36h;
  mov dl,Drive; //0-текущий,1-A,2-B и т.д.
  int 21h;
  mov SecPerClast,ax;
  mov FreeClast,bx;
  mov BytesPerSec,cx;
  mov ClastPerDrive,dx;
 }
 Volume=SecPerClast*BytesPerSec; //Байт на кластер
 if (FreeOnly) Volume*=FreeClast; //В байтах
 else Volume*=ClastPerDrive;
 if (!FULL) Volume/=1024; //In Kbytes
 return Volume;
}

void GetDate (void) {
 asm {
  mov ah,2ah;
  int 21h ;
  mov DAY,dl;
  mov MON,dh;
  mov YEAR,cx;
  mov WEEKDAY,al;
 }
}

void GetTime (void) {
 asm {
  mov ah,2ch;
  int 21h ;
  mov HOUR,ch;
  mov MIN,cl;
  mov SEC,dh;
 }
}

long GetTimer (void) {
 //Значение таймера BIOS
 asm mov ah,0;
 asm int 1ah;
 L.High=_CX;
 L.Low=_DX;
 return L.Long;
}

void SetTimer (long Time) {
 unsigned Hi,Low;
 Low=Time;
 Hi=(Time>>16);
 asm mov cx,Hi;
 asm mov dx,Low;
 asm mov ah,01h;
 asm int 1ah;
 return;
}

void DosVersion (void) {
 asm {
  mov ah,30h;
  int 21h;
  mov HIGHDOS,al;
  mov LOWDOS,ah;
 }
}

unsigned char SetVideoMode (MODE Mode) {
 // 0 -OK, 1-ERROR
 asm {
  mov ah,0;
  mov al,Mode;
  int 10h;
  mov ah,0fh;
  int 10h;
  cmp al,Mode;
  je OK;
 }
 return 1;
OK:
 MaxCol=_AH;
 MaxRow=25;
 return 0;
}

unsigned char GetVideoMode (void) {
 asm mov ah,0fh;
 asm int 10h;
 return _AL;
}

void ReadCursor(void) {
 asm mov ah,3;
 asm mov bh,0; //Page
 asm int 10h;
 RowCursor=_DH;
 ColCursor=_DL;
}

void SetCursor (unsigned char Row, unsigned char Col) {
 asm mov ah,02h;
 asm mov bh,0; //Page
 asm mov dh,Row;
 asm mov dl,Col;
 asm int 10h;
}

void SetSizeOfCursor (unsigned char Low, unsigned char Hi) {
 asm mov ah,1;
 asm mov ch,Hi;  //Верхняя линия на экране  | от 0 до 7
 asm mov cl,Low; //Нижняя линия             |
 asm int 10h;
}

unsigned char ReadChar (unsigned char *a) {
 unsigned char c;
 asm mov ah,8;
 asm mov bh,0;
 asm int 10h;
 c=_AL;
 *a=_AH;
 return c;
}

void WriteChar (unsigned char c,unsigned char a) {
 //Вывод символа с атрибутом в текущую позицию курсора
 //Не перемещает курсор !!!
 asm mov ah,9;
 asm mov al,c;
 asm mov bh,0;
 asm mov bl,a;
 asm mov cx,1;
 asm int 10h;
 return;
}

void WritePosChar (unsigned char x, unsigned char y, unsigned char c, unsigned char a) {
 SetCursor (x,y);
 WriteChar (c,a);
}

void Save(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2) {
 unsigned char i,j,a,c;
 BufPos=0;
 for (i=x1; i<=x2; i++)
 for (j=y1; j<=y2; j++) {
  SetCursor (i,j);
  c=ReadChar (&a);
  if (BufPos<BUF_LEN-1) {
   Buffer[BufPos++]=c;
   Buffer[BufPos++]=a;
  }
  else break;
 }
}

void Restore (unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2) {
 unsigned char i,j,a,c;
 BufPos=0;
 for (i=x1; i<=x2; i++)
 for (j=y1; j<=y2; j++) {
  c=Buffer[BufPos++];
  a=Buffer[BufPos++];
  WritePosChar (i,j,c,a);
 }
}

#define LAST_STYLE 2
void DrawBox (unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, unsigned char Type, unsigned char Fill) {
// Отрисовка рамки:
//  012 --¬ г=¬
//  3 4 ¦1¦ ¦2¦
//  567 L-- L=-
//Fill используется при Type=0
 unsigned char border[LAST_STYLE+1][8]={
  {' ',' ',' ',' ',' ',' ',' ',' '},
  {'-','-','¬','¦','¦','L','-','-'},
  {'г','=','¬','¦','¦','L','=','-'}
 }; unsigned char i;
 if (!Type) for (i=0; i<8; i++) border[0][i]=Fill; // Задан заполнитель
 for(i=x1; i<=x2; i++) { // Вниз
  WritePosChar (i,y1,border[Type][3],ATTR);
  WritePosChar (i,y2,border[Type][4],ATTR);
 }
 for (i=y1; i<=y2; i++) { // Вправо
  WritePosChar (x1,i,border[Type][1],ATTR);
  WritePosChar (x2,i,border[Type][6],ATTR);
 }
 WritePosChar (x1, y1, border[Type][0],ATTR);
 WritePosChar (x1, y2, border[Type][2],ATTR);
 WritePosChar (x2, y1, border[Type][5],ATTR);
 WritePosChar (x2, y2, border[Type][7],ATTR);
 return;
}

void ClearBox (unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, unsigned char attr) {
 unsigned char i,j;
 for (i=x1; i<=x2; i++)
 for (j=y1; j<=y2; j++)
  WritePosChar (i,j,' ',attr);
}

void ScrollWindow (unsigned char x1, unsigned char y1, unsigned char x2,unsigned char y2,unsigned char attr,unsigned char dir,unsigned char lines) {
 //Прокручивает окно на lines строк в направлении dir
 //Если lines=0, просто очищает окно
 unsigned char i;
 if (dir==UP_DIR) i=6;
 else i=7;
 asm {
  mov ah,i;
  mov al,lines;
  mov bh,attr;
  mov ch,x1;
  mov cl,y1;
  mov dh,x2;
  mov dl,y2;
  int 10h;
 }
}

#define DEFAULT_DELAY 6
void MakeDelay (unsigned Tics) {
asm { mov ah,0;
      int 1ah;
      add dx,Tics;
      mov bx,dx; }
CYCLE:
asm { int 1ah;
      cmp dx,bx;
      jne CYCLE; }
}

void ChangeAttr (unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, unsigned char Attr) {
 unsigned char i,j,c,a;
 for (i=x1; i<=x2; i++)
 for (j=y1; j<=y2; j++) {
  SetCursor (i,j);
  c=ReadChar (&a);
  WritePosChar (i,j,c,Attr);
 }
}

void DrawWindow (unsigned char x_1, unsigned char y_1, unsigned char x_2,unsigned char y_2,unsigned char attr) {
 unsigned char x1=x_1, y1=y_1, x2=x_2, y2=y_2, In;
 if (Explode) { //explode
  x1+=((x_2-x_1)>>1);
  x2=x1+1;
  y1+=((y_2-y_1)>>1);
  y2=y1+1; In=0x0F;
  do {
   DrawBox (x1,y1,x2,y2,Border,Filler);
   MakeDelay (DEFAULT_DELAY);
   DrawBox (x1,y1,x2,y2,0,' ');
   if (x1>x_1) x1--;
   else In&=0xfe;
   if (x2<x_2) x2++;
   else In&=0xfb;
   if (y1>y_1) y1--;
   else In&=0xfd;
   if (y2<y_2) y2++;
   else In&=0xf7;
  } while (In);
 }
 else { // normal
  ClearBox (x_1,y_1,x_2,y_2,attr);
 }
 DrawBox (x_1,y_1,x_2,y_2,Border,Filler);
 if (Shadow) { //shadow
  In=(y2<MaxCol?(y2<MaxCol-2?y2+2:MaxCol-2):MaxCol-1);
  if (y2<MaxCol-1) ChangeAttr (x1+1,y2+1,x2,y2+2,0x08); //Ver
  if (x2<MaxRow) ChangeAttr (x2+1,y1+2,x2+1,In,0x08); //Hor
 } return;
}

void WriteString (unsigned char *s,unsigned char attr) {
 unsigned char r,c;
 ReadCursor(); r=RowCursor; c=ColCursor;
 for (; *s; s++) {
  if (*s=='\n') goto NEXT;
  WriteChar (*s,attr);
  c++;
  if (c>MaxCol) {
NEXT:
   c=0; r++;
   if (r>MaxRow) break;
  }
  SetCursor (r,c);
 }
}

void WriteToCon (unsigned char *Str) {
 unsigned char c;
 for (;*Str;Str++) {
  c=*Str;
  asm mov ah,06h;
  asm mov dl,c;
  asm int 21h;
 }
}

unsigned char IsAnsi (void) {
 unsigned char *Test="\033[1D", //ANSI-строка: переместить курсор влево на 1
  c,r,Ret;
 ReadCursor(); r=RowCursor; c=ColCursor;
 Save (0,1,0,4);
 SetCursor (0,1);
 WriteToCon (Test);
 ReadCursor();
 if (ColCursor==0) Ret=YES;
 else Ret=NO;
 Restore (0,1,0,4);
 SetCursor (r,c);
 return Ret;
}

unsigned char MouseIsReady (void) {
 //0-OK,1-ERROR
 asm mov ax,0;
 asm int 33h;
 asm cmp ax,0;
 asm je ERROR;
 return 0;
ERROR: return 1;
}

void ReadString (unsigned char Maxlen) {
 //Введенная строка в Buffer со смещения 2, длина ввода в Buffer[1]
 //MaxLen включает символ конца строки
 Buffer[0]=Maxlen;
 Buffer[1]='\0';
 asm mov ah,0ah;
 asm lea dx,Buffer;
 asm int 21h;
}

void SetColor (unsigned char Color) {
 ATTR&=0xF0;
 ATTR|=Color|0x0F;
}
void SetBkColor (unsigned char BkColor) {
 ATTR&=0x0F;
 ATTR|=((BkColor&0x0F)<<4);
}

long GetFileSize (unsigned char *Name) {
 // -1 Ошибка, иначе размер файла
 int Handle;
 asm mov ax,seg Name;
 asm mov ds,ax;
 asm mov dx,offset Name;
 asm mov ax,3d00h;
 asm int 21h;
 asm jc ERROR;
 asm mov Handle,ax;
 asm mov ax,4202h;
 asm mov bx,Handle;
 asm mov cx,0;
 asm mov dx,0;
 asm int 21h;
 asm jc ERROR;
 L.High=_DX;
 L.Low=_AX;
 return L.Long;
ERROR:
 return -1L;
}

void Clear_Buf(void) {
asm  cli;
asm  sub ax,ax;
asm  mov es,ax;
asm  mov al,es:[41ah];
asm  mov es:[41ch],al;
asm  sti;
}

int Hit_Key(void) {
asm  mov ax,0;
asm  mov es,ax;
asm  mov al,es:[41ah];
asm  mov ah,es:[41ch];
if (_AH==_AL) return (0);
return (1);
}

void SecDelay (unsigned Sec) {
 unsigned u; unsigned char Count=0;
 for (u=Sec; u>0; u--) {
  MakeDelay (18);
  if (Break && Hit_Key()) { Clear_Buf(); break; }
  Count++;
  if (Count==60) { Count=0; MakeDelay (12); }
 }
}

unsigned Seconds (unsigned char h, unsigned char m, unsigned char s) {
 return (h*3600u+m*60u+s);
}

unsigned KolSeconds (unsigned char h1, unsigned char m1, unsigned char s1,unsigned char h2, unsigned char m2, unsigned char s2) {
 unsigned t1,t2;
 t1=Seconds (h1,m1,s1);
 t2=Seconds (h2,m2,s2);
 if (t1<=t2) return (t2-t1);
 return (20864-t1+t2);
}

void TimeWait (unsigned char hour, unsigned char min, unsigned char sec) {
 unsigned Sec;
 GetTime();
 Sec= KolSeconds (HOUR,MIN,SEC,hour,min,sec);
 SecDelay (Sec);
}

long GetTics (unsigned Sec) {
 //Примерное число "тиков" в Sec секундах
 long L;
 L=Sec*18+ Sec/5+ (Sec%2>2?1:0);
 return L;
}

unsigned char AskKey (unsigned char *Keys, unsigned char Delay, unsigned char Case, unsigned char Default, unsigned char Show) {
 //Delay=0 - ждать нажатия, иначе через Delay секунд выбрать номер Default
 //Case=1 - не различать строчные и прописные
 //Show=1 - показать выбор с новой строки
 unsigned char c,s,Len,i; long Timer;
 Len=StrLen (Keys);
 if (Case) UpCaseStr (Keys);
 if (Show) {
  WriteString ("[",ATTR);
  WriteString (Keys,ATTR);
  WriteString ("]? ",ATTR);
 }
 if (Delay) {
  Timer=GetTimer()+GetTics(Delay);
  if (Timer>1572480L) Timer=1572480L-Timer;
 }
 Clear_Buf();
 while (1) {
  if (Delay) while (!Hit_Key()) {
   if (GetTimer()>=Timer) {
    i=Default-1; c=*(Keys+i); goto OUT;
   }
  }
  c=(unsigned char)Get_Key();
  for (i=0; i<Len; i++) {
   s=*(Keys+i);
   if (s==c || (Case && (UpCase(s)==UpCase(c)) ) ) {
OUT:
    if (Show) WriteChar (c,ATTR);
    return (i+1);
   }
  }
 }
}

void Sound (unsigned Sec, unsigned Freq) {
 long Time=GetTimer();
 asm{
  PUSH  AX   //Сохраняем используемые регистры
  PUSH  BX
  PUSH  CX
  PUSH  DX
  PUSH  DI
  CLI                  //Запрещаем прерывания
  MOV   DI,Freq       //Переносим значения в регистры
  MOV   BX,Sec
  MOV   AL,0B6H      //Записать в регистр режима таймера
  OUT   43H,AL
  MOV   DX,14H       //Длительность времени =
  MOV   AX,4F38H     //1331000 / частота
  DIV   DI
  OUT   42H,AL       //Записать младший байт счетчика таймера 2
  MOV   AL,AH
  OUT   42H,AL       //Записать старший байт счетчика таймера 2
  IN    AL,61H       //Считать текущую установку порта В
  MOV   AH,AL        //и сохранить ее в регистре AH
  OR    AL,03H       //Включить динамик
  OUT   61H,AL
 }
WAIT: asm  MOV   CX,2A00H     //Выждать 10 мс
SPKR: asm{
  LOOP  SPKR
  DEC   BX           //Счетчик длительности исчерпан ?
  JNZ   WAIT         //Нет. Продолжить звучание
  MOV   AL,AH        //Да. Восстаносить исходную установку порта
  OUT   61H,AL
  POP   DI           //Востановить регистры
  POP   DX
  POP   CX
  POP   BX
  POP   AX
  STI                //Разрешить прерывания
 }
 SetTimer (Time+Sec);
 return;
}


unsigned GetMemory (void) {
 unsigned FreeMemorySize;
 unsigned Par;
 asm mov bx,0ffffh;
 asm mov ah,48h;
 asm int 21h;
 Par=_BX;
 FreeMemorySize=(((long)Par)<<4)/1024;
 return FreeMemorySize;
}

////////////////////////////////////////////////////////////////////////
void CheckString(void) {
 if (SetString) UtoA (Return,String);
}



unsigned char *Months[]={ "января","февраля","марта","апреля","мая","июня",
 "июля","августа","сентября","октября","ноября","декабря" };
unsigned char *WeekDays[]={ "понедельник","вторник","среда","четверг","пятница",
 "суббота","воскресенье" };

void Day (void) { GetDate(); Return=DAY; CheckString(); }

void WeekDay (void) {
 GetDate(); Return=(WEEKDAY==0 ? 7 : WEEKDAY);
 if (FullFormat) StrCpy (String, WeekDays[Return-1]);
 else CheckString();
}

void Month (void) {
 unsigned char Len;
 GetDate(); Return=MON;
 if (FullFormat) {
  StrCpy (String, Months[MON-1]);
  Len=StrLen (String);
  if (MON==0x08) String[Len-1]='\0';
  else String[Len-1]='ь';
 }
 else CheckString();
}

void Year (void) {
 GetDate();
 Return=YEAR%100;
 CheckString();
}

void GetDateString (unsigned char *Ptr1, unsigned char *Ptr2, unsigned char *Ptr3) {
 unsigned char *Str=" \0";
 Str[0]=DateDividor;
 StrCpy (String,Ptr1);
 StrCat (String,Str);
 StrCat (String,Ptr2);
 StrCat (String,Str);
 StrCat (String,Ptr3);
}

void Date (void) {
 unsigned char *DayPtr=&String[20],*MonPtr=&String[40],*YearPtr=&String[60];
 GetDate();
 UtoA (DAY,DayPtr);
 if (FullFormat) StrCpy (MonPtr, Months[MON-1]);
 else UtoA (MON,MonPtr);
 if (DateFormat%2) UtoA (YEAR,YearPtr);
 else UtoA (YEAR%100,YearPtr);
 if (DateFormat<2) { //MDY[Y]
  GetDateString (MonPtr,DayPtr,YearPtr);
 }
 else if (DateFormat<4) { //DMY[Y]
  GetDateString (DayPtr,MonPtr,YearPtr);
 }
 else if (DateFormat<6) { //Y[Y]MD
  GetDateString (YearPtr,MonPtr,DayPtr);
 }
 else { //Y[Y]DM
  GetDateString (YearPtr,DayPtr,MonPtr);
 }
}

void Hour (void) { GetTime(); Return=HOUR; CheckString(); }
void Minute (void) { GetTime(); Return=MIN; CheckString(); }
void Second (void) { GetTime(); Return=SEC; CheckString(); }

#define HM 0
#define HMS 1

void Time (void) {
 unsigned char Len;
 GetTime();
 UtoA (HOUR,String);
 Len=StrLen(String);
 String[Len]=TimeDividor;
 UtoA (MIN,&String[Len]);
 if (FullFormat) {
  Len=StrLen (String);
  String[Len]=TimeDividor;
  UtoA (SEC,&String[Len]);
 }
}

void Exit (unsigned char RetCode) {
 asm mov al,RetCode;
 asm mov ah,0x4c;
 asm int 21h;
}

void main () { //тест функций
 ClearBox (0,0,24,79,0x07); SetCursor (1,1);
 printf ("\nUpCase: %c", UpCase ('р'));
 unsigned char *s="тест Test";
 UpCaseStr (s);
 printf ("\nUpCaseStr: %s", s);
 printf ("\nStrCmp: %d",StrCmp("1001","1000",0));
 printf ("\nStrChr: %s",StrChr("1001",'0'));
 printf ("\nStrRChr: %s",StrRChr("1001",'0'));
 printf ("\nStrTok: %s",StrTok("10020","01"));
 s="00000";
 StrSet(s,'x',3);
 printf ("\nStrSet: %s",s);
 printf ("\nIsDigit('0'), IsSpace('\\r'), IsUnsigned (\"-1\"): %d %d %d",
   IsDigit('0'), IsSpace('\r'), IsUnsigned ("-1"));
 printf ("\nAtoU(\"1000\"): %u",AtoU("1000"));
 printf ("\nStrLen(\"abcde\"): %d",StrLen("abcde"));
 s="abcde";
 StrRev(s);
 printf ("\nStrRev(\"abcde\"): %s",s);
 s="    ";
 UtoA(1234,s);
 printf ("\nUtoA(1234,s): %s",s);
 unsigned char *d="1234____";
 d=StrCat(d,s);
 printf ("\nStrCat: %s",d);
 StrCpy(d,s);
 printf ("\nStrCpy: %s",d);
 printf ("\n Free any key:");
 printf ("\n Key code: %d",Get_Key());
 WritePosString (10,10,"String with attributes - WritePosString ",0x70);
 ClearBox (0,0,24,79,0x07);
 unsigned char *menu[3] = { "GetPopup menu", "function", "demo" };
 GetPopup (1,1,3,menu,1);
 StrCpy(menu[0],"GetMenu");
 GetMenu (0,0,3,menu,1);
 printf ("\nPrinterIsReady(0): %d",PrinterIsReady(0));
 printf ("\nDriveReady(current): %d",DriveReady(0));
 HardStatus();
 printf ("\nHardStatus: IsSoprocessor=%d, KolFlops=%d, ActiveVideo=%d, KolPrinters=%d, BaseMemorySize=%d",
  IsSoprocessor, KolFlops, ActiveVideo, KolPrinters, BaseMemorySize);
 printf ("\nGetDrive(): %d",GetDrive());
 printf ("\nSetDrive(2) returns %d",SetDrive(2));
 GetDirectory (3);
 printf ("\nGetDirectory (3) sets in Buffer: %s",Buffer);
 printf ("\nDiskSpace (3,0)=%ld,DiskSpace (3,1)=%ld",DiskSpace (3,0),DiskSpace (3,1));
 printf ("\n Et cetera... press a key to exit");
 Get_Key();
}

Рейтинг@Mail.ru

вверх гостевая; E-mail