mcb.dest.handle = emm_handle; /*предварительно
размещенный обpаботчик*/
mcb.dest.initial_offset = sp->scr_offset; /*следующее до-
ступное смещение*/
mcb.dest.initial_seg_page = sp->scr_page; /*в текущей стра-
нице*/
if (rc = EMSMoveRegion(&mcb)) /*функция "Передвинуть область
памяти" спецификации pасшиpенной памяти*/
return(rc); /*отказ*/
Beep(1000); /*выдать короткий звуковой сигнал - успех*/
/*обновить индексные данные экрана ("Передвинуть область" не
нарушает контекста отображения*/
ip->scr_count++; /*уменьшение кол-ва сохраненных экранов*/
sp->scr_len = src_size; /*запомнить кол-во байтов на экране*/
sp->scr_width = vp->crt_cols;/*запомнить кол-во колонок в
строке*/
sp++; /*указать на следующий индексный элемент*/
sp->scr_len = 0; /*новый еще не снятый экран,*/
sp->scr_width = 0; /*поэтому нулевые длина и ширина*/
sp->scr_page = emm_pages -1; /*новый экран идет на послед-
нюю размещенную страницу,*/
sp->scr_offset = new_offset; /*непосредственно следуя за
предыдущим экраном*/
return(rc); /*успех*/
}
/*освободить расширенную память, если размещена*/
cleanup()
{
int rc;
/*игнорировать код возврата, так как вызов может быть из
ошибочной процедуры*/
if (emm_handle != -1)
rc = EMSDeallocatePages(emm_handle);
}
#pragma check_stack(on)
- 7-80 -
main(argc, argv)
int argc;
char *argv[];
{
int emm_present, rc;
unsigned int far *pseg_top;
char emm_ver[4];
get_opts(argc, argv); /*получить переключатели командной
строки*/
emm_handle = -1; /*нет размещенных обpаботчиков
pасшиpенной памяти*/
/*установить драйвер "Control-C" (прерывание)*/
signal(SIGINT, break_handler);
/*проверка наличия pасшиpенной памяти*/
if (rc = emm_exists(emm_present)) { /*тест наличия
менеджеpа pасшиpенной памяти не прошел*/
printf("snapshot: EMM presence test failed, rc: %d", rc);
exit(2);
}
if (!emm_present) { /*нет pасшиpенной памяти*/
printf("snapshot: No expanded memory is present");
exit(1);
}
/*получить версию спецификации pасшиpенной памяти, которую
поддерживает менеджеp pасшиpенной памяти*/
if (rc = EMSGetVersion(emm_ver)) {
DisplayError(rc);
exit(1);
}
/*убедитесь, что это - по крайней мере, версия 4.0*/
if (*emm_ver < '4') { /*требуется спецификация pасшиpенной
памяти LIM 4.0 или выше*/
printf("snapshot: Unsupported EMM version detected: %s,
LIM EMS 4.0 or greater is required", emm_ver);
exit(1);
}
/*получить указатель на кадр страниц спецификации pасшиpенной
памяти*/
if (rc = EMSGetFrameAddr(&page_frame)) {
DisplayError(rc);
exit(1);
}
/*поиск обpаботчика спецификации pасшиpенной памяти, который
содержит запомненные экраны*/
- 7-81 -
rc = EMSSearchHandleName(HANDLE_NAME, &emm_handle);
/*ошибка, если любой код возврата, отличный от 'нормально'
или 'обpаботчик не найден'*/
if (rc != 0 && rc != HNDVLNFD) {
DisplayError(rc);
exit(1);
}
/*или закончить и остаться резидентно, установить программу,
остающуюся после завершения резидентно, или показать ее текущее
состояние*/
if (terminate_flag) { /*пользователь запросил завершение*/
if (rc == 0) /*обpаботчик с нашим именем существует,*/
terminate(); /*поэтому постараться снять себя*/
else { /*обpаботчик не существует, поэтому не мо-
жет завершиться */
printf("snapshot: can't terminate - not installed");
exit(1);
}
} else { /*или установиться или выдать состояние*/
/* если обработчик, именованный HANDLE_NAME, уже сущест-*/
/*вует, только сообщить, сколько памяти спецификации */
/*расшиpенной памяти в настоящий момент размещено, и как*/
/*много экранов хранится в ней. В противном случае, уста-*/
/*новить программу обслуживания прерывания для прерывания*/
/*печати и сделать данную программу резидентной*/
if (rc == 0) /*обpаботчик с нашим именем уже сущест-*/
show_status(); /*вует,поэтому только показать состоя-
ние*/
else { /*обpаботчик не существует,*/
install(); /*поэтому разместить обpаботчик и уста-
новить программу обработки прерывания*/
/*завершиться и остаться резидентно*/
FP_SEG(pseg_top) = _psp; /*конечный параграф програм-
мы находится по psp+2 */
FP_OFF(pseg_top) = 2;
printf("snapshot: TSR installing at segment [%04X],
size %u paragraphs\n", _psp, *pseg_top - _psp);
_dos_keep(0, *pseg_top - _psp); /*кол-во параграфов
в программе*/
}
}
}
/*отобразить идентификатор обpаботчика, кол-во логических*/
/*страниц, размещенных для него, и кол-во экранов, запомнен-*/
- 7-82 -
/*ных в данный момент в pасшиpенной памяти*/
show_status()
{
int rc;
unsigned int alloc_pages, screens;
/*определение кол-ва страниц, размещенных для данного обpа-*/
/*ботчика менеджеpа pасшиpенной памяти*/
if (rc = EMSGetHandlePages(emm_handle, &alloc_pages)) {
DisplayError(rc);
cleanup();
exit(1);
}
/*отобразить первую логическую страницу, содержащую индекс
экрана, в нулевую физическую страницу*/
if (rc = EMSMapHandlePage(emm_handle, 0, 0)) {
DisplayError(rc);
cleanup();
exit(1);
}
/*получить адресуемость для структуры данных индексов экранов
в pасшиpенной памяти*/
ip = (SCR_INDEX far *) page_frame;
/*печатать текущее состояние*/
printf("snapshot: status - EMS handle (%d); EMS
pages (%d); screens (%d)\n", emm_handle, alloc_pages,
ip->scr_count);
/*перестать отображать страницу индексов экрана*/
if (rc = EMSMapHandlePage(emm_handle, -1, 0)) {
DisplayError(rc);
cleanup();
exit(1);
}
}
/*Получить обpаботчик спецификации pасшиpенной памяти с од-*/
/*ной страницей от менеджеpа pасшиpенной памяти и дать ему*/
/*наименование, так чтобы другие программы могли обращаться*/
/*к нему. Инициализировать структуру индексных данных экра-*/
/*нов, которая будет размещена в начале первой страницы спе-*/
/*цификации pасшиpенной памяти. Затем подставьте программу*/
/*обслуживания прерывания для прерывания печати экрана, так*/
/*чтобы образы экранов сохранялись в pасшиpенной памяти, */
/*когда пользователь нажимает клавишу PrtScr.*/
install()
- 7-83 -
{
int rc, context_bytes;
/*разместить одну страницу для начала*/
emm_pages = 1;
if (rc = EMSAllocatePages(&emm_handle, emm_pages)) {
DisplayError(rc);
exit(1);
}
/*дать обpаботчику имя, так чтобы другие программы могли */
/* найти его */
if (rc = EMSSeyHandleName(emm_handle, HANDLE_NAME)) {
DisplayError(rc);
cleanup();
exit(1);
}
printf("snapshot: allocated expanded memory handle # %d with
name '%s'\n", emm_handle, HANDLE_NAME);
/* инициализировать данные в странице индексов экранов,*/
/* которые будут запоминаться в логической странице 0 */
if (rc = EMSMapHandlePage(emm_handle, 0, 0)) {
DisplayError(rc);
cleanup();
exit(1);
}
/*получить адресуемость для структуры данных индексов экранов
в pасшиpенной памяти*/
ip = (SCR_INDEX far *) page_frame;
/* инициализировать данные в ней */
ip->scr_count = 0; /*кол-во сохраненных экранов*/
ip->scr_max = MAX_SCR; /*максимальное кол-во сохранен-
ных экранов*/
ip->scr_int5 = int5_isr; /*указатель на нашу программу
обслуживания прерывания печати экрана*/
sp = ip->scr_idx; /* -> первый индексный элемент*/
sp->scr_page = sizeof(*ip) / PAGE_SIZE; /*экраны начинаются*/
sp->scr_offset = sizeof(*ip) % PAGE_SIZE;
/*сразу за индексом*/
sp->scr_len = 0; /*вначале пусто*/
sp->scr_width = 0;
/*перестать отображать страницу индексов экрана*/
if (rc = EMSMapHandlePage(emm_handle, -1, 0)) {
DisplayError(rc);
cleanup();
exit(1);
}
- 7-84 -
/*разместить область сохранения контекста pасшиpенной памяти,
используемую драйвером прерывания печати экрана*/
if (rc = EMSGetPageMapSize(&context_bytes)) {
DisplayError(rc);