#include #include "ml.h" #define _IN_MOUSE #include "ml_mouse.h" /* text pointer selectors */ #define software_pointer 0 #define hardware_pointer 1 #define ms_call 0x33 /* номеp пpеpывания мыши */ #define iret 0xCF /* iret (return from interrupt) (возвpащение из пpеpывания) инстpукция */ #define INTR(intno,regs) intr(intno,regs) /* пpизнак пpисутствия мыши, инициализиpуется mouse_init */ boolean mouse_present; static struct REGPACK r; /* cтаpтовые Pегистpовые пеpеменные */ static void *mi; /* вектоp мышиного пpеpывания для инициализации теста */ /* Следующие функции используются для pазделения указателя на сегмент и смещение */ /*============================================================== ms_init real-mode mouse function 0 ============================================================== Возвpащает TRUE и инициализиpует мышь если мышиный дpайвеp установлен и FALSE если мышь не пpисутствует. nButtons содеpжит число кнопок на мыши. Мышь инициализиpуется со следующими значениями по умолчанию: позиция : центp экpана pointer-draw flag : -1 (pointer hidden) указатель-состояние флага : -1 (указатель скpыт (сбpошен)) гpафический указатель : image по умолчанию текстовой указатель : reverse video (обpащение изобpажения) маска пpеpывания : 0, не определен режим употребления эмуляция светового пеpа : on (включено) Mickeys/pixel(horizontal) : 8:8 Mickeys/pixel(vertical) : 16:8 min/max position : зависит от pежима дисплея */ boolean ms_init(int *nButtons) { if(mouse_present) { r.r_ax=0; INTR(ms_call,&r); if(r.r_ax==0) { /* нет мыши */ *nButtons=0; return FALSE; } else { *nButtons=r.r_bx; return TRUE; } } else { nButtons=0; return FALSE; } } /* ============================================================== ms_show real-mode mouse function 1 ============================================================== Функция 1 отображает указатель-курсор "мыши". Она не возвращает никакого значения. Если указатель-курсор уже виден, то ничего не делается. Если указатель-состояние флага не 0, то устанавливается флаг. Если указатель-состояние флага установлен в 0, высвечивается образ указателя. */ void ms_show(void) { r.r_ax=1; INTR(ms_call,&r); } /*============================================================== ms_hide real-mode mouse function 2 ============================================================== Сброс (уменьшение) указателя-состояние флага. Если указатель-курсор уже скрыт (погашен), тогда return. Если указатель-состояние флага сброшен в -1, тогда указатель-курсор скрывается (гасится). В любом случае указатель-состояние флага сбрасывается (уменьшается) */ void ms_hide() { r.r_ax=2; INTR(ms_call,&r); } /*============================================================== ms_read real-mode mouse function 3 ============================================================== Читает статус кнопок мыши и экранные координаты указателя-курсора. Экранные координаты определяются в области виртуального экрана (режимно зависимо). Буттоны нажаты если установлены следующие биты: 2-button mouse: bit 0=left button bit 1=right button 3-button mouse: bit 0=left button bit 1=right button bit 2=Center button Это означает следующее: если указанный бит установлен(= 1 ), то соответствующая клавиша была нажата, если не установлен(= 0 ) - то не нажата. */ void ms_read(unsigned *x, unsigned *y, unsigned *b_mask) { r.r_ax=3; INTR(ms_call,&r); *x=r.r_cx; *y=r.r_dx; *b_mask=r.r_bx; } /*============================================================== ms_set_pos real-mode mouse function 4 ============================================================== Функция 4 устанавливает месторасположение курсора "мыши". Значение x определяет горизонтальную позицию, а значение y - вертикальную позицию курсора. Необходимо помнить, что значения не должны выходить за пределы текущего виртуального экрана, иначе они будут обрубаться в соответствие с min/max значениями. */ void ms_set_pos(unsigned x, unsigned y) { r.r_ax=4; r.r_cx=x; r.r_dx=y; INTR(ms_call,&r); } /* ============================================================== ms_get_b real-mode mouse function 5 ============================================================== Возвращает статус нажатия кнопок мыши. count содержит число нажатий клавиши со времени последнего обращения к этой функции. The count восстанавливается в 0. Не определяет переполнение счетчика нажатий клавиши. last_x, last_y - экранные координаты указателя во время последнего нажатия клавиши. */ unsigned ms_get_b(unsigned b_mask, unsigned *count, unsigned *last_x, unsigned *last_y) { r.r_ax=5; r.r_bx=b_mask; INTR(ms_call,&r); *count =r.r_bx; *last_x =r.r_cx; *last_y =r.r_dx; return r.r_ax; } /*============================================================== ms_get_b_release real-mode mouse function 6 ============================================================== Возвращает число освобождений (отжатий) клавиши мыши. count содержит число отжатий клавиши с момента последнего обращения к этой функции. Count восстанавливается в 0. Не определяет переполнение счетчика отжатий клавиши. last_x, last_y - экранные координаты указателя-курсора во время последнего отжатия клавиши. */ unsigned ms_get_b_release(unsigned b_mask, unsigned *count, unsigned *last_x, unsigned *last_y) { r.r_ax=6; r.r_bx=b_mask; INTR(ms_call,&r); *count =r.r_bx; *last_x=r.r_cx; *last_y=r.r_dx; return r.r_ax; } /*============================================================== ms_set_hminmax real-mode mouse function 7 ============================================================== Устанавливает ограничение горизонтального движения мыши в указанных пределах. Если min>max то они меняются местами. min/max фиксируют размеры виртуального экрана. Если указатель мыши вышел за пределы, то он переносится на внутреннюю границу области (фактически останавливается на границе) */ void ms_set_hminmax(unsigned min, unsigned max) { r.r_ax=7; r.r_cx=min; r.r_dx=max; INTR(ms_call,&r); } /*============================================================== ms_set_vminmax real-mode mouse function 8 ============================================================== Устанавливает ограничение вертикального движения мыши в указанных пределах. Если min>max то они меняются местами. min/max фиксируют размеры виртуального экрана. Если указатель мыши вышел за пределы, то он переносится на внутреннюю границу области (фактически останавливается на границе) */ void ms_set_vminmax(unsigned min, unsigned max) { r.r_ax=8; r.r_cx=min; r.r_dx=max; INTR(ms_call,&r); } /*============================================================== ms_set_graphPointer real-mode mouse function 9 ============================================================== hotx, hoty (+/-16) расстояния (относительные координаты) от центра острия образа указателя вверх и влево. image=указатель на битовую карту указателя мыши Первые 32 байта определяют экранную маску. Последние 32 байта определяют маску указателя. Указатель вычерчивается (рисуется) с помощью: or экранная маска вместе с пискселами под указателем, Xor маска указателя вместе с результатом. При mode 6, каждый бит определяет цвет пиксела. При modes 4 и 5, каждая пара битов определяет цвет пиксела. */ void ms_set_graphPointer(unsigned hotx, unsigned hoty, void *image) { r.r_ax=9; r.r_bx=hotx; r.r_cx=hoty; r.r_dx=FP_OFF(image); r.r_es=FP_SEG(image); INTR(ms_call,&r); } /*============================================================== ms_set_textPointer real-mode mouse function 10 ============================================================== Выбирает тип указателя : software или hardware */ void ms_set_textPointer(unsigned select, char screen_char, char screen_attr, char pointer_char, char pointer_attr) { union REGS r1; r1.x.ax=10; r1.x.bx=select; r1.x.cx=screen_char; r1.h.ch=screen_attr; r1.h.dl=pointer_char; r1.h.dh=pointer_attr; int86(ms_call,&r1,&r1); } /*============================================================== ms_read_motion real-mode mouse function 11 ============================================================== Возвращает число мышиных шагов на какое переместилась мышь со времени последнего вызова этой функции. Положительное число означает вправо/вниз. Восстанавливает счетчики в 0. */ void ms_read_motion(unsigned *hCount, unsigned *vCount) { r.r_ax=11; INTR(ms_call,&r); *hCount=r.r_cx; *vCount=r.r_dx; } /*============================================================== ms_set_routine real-mode mouse function 12 ============================================================== Устанавливает вызов маски и адрес подпрограммы для самостоятельного определения управления прерываниями устройством мышь. mouse hardware interrupt horler.r_ */ void ms_set_routine(unsigned call_mask, void *sub) { r.r_ax=12; r.r_cx=call_mask; r.r_dx=FP_OFF(sub); r.r_es=FP_SEG(sub); INTR(ms_call,&r); } /*============================================================== ms_lightpen_on real-mode mouse function 13 ============================================================== включить эмуляцию светового пера */ void ms_lightpen_on(void) { r.r_ax=13; INTR(ms_call,&r); } /*============================================================== ms_lightpen_off real-mode mouse function 14 ============================================================== выключить эмуляцию светового пера */ void ms_lightpen_off(void) { r.r_ax=14; INTR(ms_call,&r); } /*============================================================== ms_set_MPP real-mode mouse function 15 ============================================================== Установить горизонтальную и вертикальную норму движения мыши. MPP (1 <= MPP <= 32767)=Mickeys / 8 pixels по умолчанию hMPP is 8:8 по умолчанию vMPP is 16:8 */ void ms_set_MPP(unsigned hMPP, unsigned vMPP) { if(hMPP >= 1 && hMPP <= 32767 && vMPP >= 1 && vMPP <= 32767) { r.r_ax=15; r.r_cx=hMPP; r.r_dx=vMPP; INTR(ms_call,&r); } } /*================================================================ ms_cond_off real-mode mouse function 16 ================================================================ Если указатель-курсор находится в определенной области, эта функция скрывает (гасит) указатель пока область не будет переопределена. После окончания действия этой функции, необходимо вызвать функцию 1 (ms_show) для появления указателя-курсора снова. Координаты указываются в пикселах. Кстати: top - верхняя граница области, left - левая bottom - дно right - правая */ void ms_cond_off(unsigned top, unsigned left, unsigned bottom, unsigned right) { r.r_ax=16; r.r_cx=left; r.r_dx=top; r.r_si=right; r.r_di=bottom; INTR(ms_call,&r); } /*================================================================ ms_set_2speed real-mode mouse function 19 ================================================================ Устанавливает интервал опроса положения указателя-курсора на экране, определяемый в Mickeys/сек. По умолчанию интервал определен в 128 Mickeys/сек. */ void ms_set_2speed( unsigned MPS) { r.r_ax=19; r.r_dx=MPS; INTR(ms_call,&r); } /*================================================================ ms_swap_routine real-mode mouse function 20 ================================================================ Устанавливает маску и управление прерыванием. Возвращает прежнюю маску и вектор прерывания. В вызове процедуры для управления преррыванием мыши должно быть примерно следующее: void interrupt myMouseInt(unsigned Flags, unsigned CS, unsigned IP, (* не используется *) unsigned condition_mask, unsigned b_state, unsigned hPos, unsigned vPos, unsigned lastVM, unsigned lastHM) The interrupt routine will be called with the following values in the registers: Текущее прерывание должно быть вызвано со следующими величинами в регистрах: ax : состояние маски (bit установлен =состояние местоопределено) bx : статус клавиши cx : горизонтальная координата указателя-курсора dx : вертикальная координата указателя-курсора si : последний снятый вертикальный Mickey счетчик di : последний снятый горизонтальный Mickey счетчик DS должен содержать адрес сегмента содержащего сегмента данных драйвера мыши, следовательно текущее прерывание должно устанав- ливать DS на этот свой собственный сегмент данных. */ void ms_swap_routine(unsigned call_mask, void *sub, unsigned *last_call_mask, void **last_sub) { r.r_ax=20; r.r_cx=call_mask; r.r_dx=FP_OFF(sub); r.r_es=FP_SEG(sub); INTR(ms_call,&r); *last_call_mask=r.r_cx; *last_sub=MK_FP(r.r_es,r.r_dx); } /*================================================================ ms_get_state_bfsz real-mode mouse function 21 ================================================================ Возвращает размер буфера в байтах, требующихся для сохранения состояния драйвера мыши. */ unsigned ms_get_state_bfsz(void) { r.r_ax=21; INTR(ms_call,&r); return r.r_bx; } /*================================================================ ms_get_state real-mode mouse function 22 ================================================================ Получить статус драйвера мыши. */ void ms_get_state(void *ms_state) { r.r_ax=22; r.r_dx=FP_OFF(ms_state); r.r_es=FP_SEG(ms_state); INTR(ms_call,&r); } /*================================================================ ms_set_state real-mode mouse function 23 ================================================================ Установить статус драйвера мыши, полученный при предшествующем сохранении статуса. */ void ms_set_state(void *ms_state) { r.r_ax=23; r.r_dx=FP_OFF(ms_state); r.r_es=FP_SEG(ms_state); INTR(ms_call,&r); } /*================================================================ MousePressed ================================================================ Возвращает TRUE если была нажата какая-то из клавиш мыши */ boolean mouse_pressed(void) { if(!mouse_present) return FALSE; else { r.r_ax=3; INTR(ms_call,&r); if(r.r_bx==0x0000) return FALSE; else return TRUE; } } /*================================================================ MouseKeyWord ================================================================ Возвращает псевдо-скан код нажатых клавиш мыши */ unsigned mousekeyword(void) { r.r_ax=3; INTR(ms_call,&r); switch(r.r_bx) { case 0x0001 : return ms_L; case 0x0002 : return ms_R; case 0x0003 : return ms_LR; case 0x0004 : return ms_C; case 0x0005 : return ms_LC; case 0x0006 : return ms_RC; case 0x0007 : return ms_LRC; } return 0; } /*=============== initialization =================================*/ void mouse_init(void) { mi=(void *)getvect(ms_call); if(mi==NULL) /* Мышиный вектор прерывания null */ mouse_present=FALSE; else if(*(char *)mi==iret) /* точки вектора в iret */ mouse_present=FALSE; else mouse_present=TRUE; } /* mouse unit */