Страница 17 из 20
6.3.2 Выравнивание правого поля. Реальное выравнивание правого поля заключается в распределении пробелов, находящихся в конце строки, равномерно по промежуткам между словами. Некоторые принтеры имеют специальный режим, кото- рый автоматически осуществляет это выравнивание. Такую возмож- ность имеет цветной принтер IBM, посылка управляющего кода 27,77,0 заставляет электронику принтера интерпретировать посту- пающие данные и форматировать их. В других случаях принтер должен менять ширину пробелов между словами, переключаясь в графический режим, когда выводится символ пробела. В графических режимах ширина пробела может изменяться на размер до 1/6 размера символа. К сожалению, многие принтеры на некоторое время останавливаются при переключении между текстовым и графическим режимами, поэтому такой метод может оказаться слишком медленным. Другой подход состоит во вставке обычных символов пробела, распределяя их как можно более равномерно по строке. Более сложный графический под- ход описан ниже. Шаги, которые необходимо выполнить для форматирования с вырав- ниванием правого поля, следующие. Во-первых, из установок формата страницы должно быть вычислено число символов в строке. Затем необходимо подсчитать число символов, занимаемое каждым из после- довательно введенных слов, включая пробелы между словами. Отдель- ный счетчик должен подсчитывать число пробелов. Когда общая сумма символов превзойдет 80 (или ту ширину принтера, которая установ- лена), то последнее слово должно быть отброшено из этой суммы, вместе с предшествующим ему пробелом. Число оставшихся свободными позиций в строке умножается на 6, поскольку каждый символ зани- мает размер шести точек по горизонтали, а получившееся число делится на число пробелов между словами. После печати каждого слова принтер устанавливается в графичес- кий режим 480 точек в строке и посылает на принтер ряд кодов ASCII 0. Каждый такой байт сдвигает печатающую головку на одну точку вправо. Посылаемое число должно быть равно шести для обыч- ного пробела, плюс результат распределения пустого пространства. Наконец, если остаток от деления ненулевой, то надо добавить по одному добавочному байту к первым пробелам, до тех пор пока оста- ток не будет исчерпан.
Для примера рассмотрим случай, когда строка состоит из 12 слов, содержащих 61 букву, плюс 11 пробелов между словами. Это оставляет в 80-тисимвольной строке 8 свободных позиций. Эти во- семь позиций, умноженные на 6 точек, составляют 48 точек дополни- тельного пространства строки. Поскольку в строке 11 пробелов, то к каждому из них должно быть добавлено по 4 дополнительные точки и после этого останутся еще 4 лишние точки, которые надо добавить по одной к первым четырем пробелам. Тогда первые 4 пробела будут иметь размер 6 точек нормального пробела, плюс добавочные 5, что в сумме равно 11. Остальные пробелы этой строки будут иметь раз- мер 10 точек. Чтобы послать эти данные на принтер, подготовьте сначала код, посылающий на принтер 1 байт ASCII 0, а затем помес- тите его в цикл, который выполняйте столько раз, сколько нужно послать таких байтов. На рис. 6-2 показан этот процесс. В нижеприведенном примере показаны основы выравнивания по правому полю. Не забудьте об обработке специальных случаев, таких как слово, которое длиннее строки (напр., длинный ряд тире). Процедура нуждается в модификации, которая позволяла бы ей иметь дело со случаем, когда строка содержит всего несколько слов, как это бывает в конце параграфа. Не позволяйте ей распределить эти слова равномерно по всей ширине страницы.
Высокий уровень. В данном примере, BUFFERPTR указывает на место в буфере дан- ных, с которого начинается следующая строка, выводимая на печать.
100 S$ = "This text will be printed with right justification using the printer alternately in text modes and graphics modes." 110 STRINGPTR = 1 'указатель в строке данных S$ 120 COLUMNS = 1 'счетчик позиции в строке 130 SPACES = 0 'счетчик пробелов в строке 140 '''вычисляем сколько слов помещается в строке 150 C$ = MID$(S$,STRINGPTR,1) 'получаем символ 160 IF C$ <> " " THEN 190 'если не пробел, то вперед 170 LASTSPACE = COLUMNS 'иначе зпоминаем позицию 180 SPACES = SPACES + 1 'увеличиваем число пробелов 190 COLUMNS = COLUMNS+1 'увеличиваем указатель столбца 200 STRINGPTR = STRINGPTR + 1 'увеличиваем указатель данных 210 IF COLUMNS = 81 THEN 230 'уход по концу строки 220 GOTO 150 'иначе к следующему символу 230 IF C$ <> " " THEN 270 'если последний не пробел, то уход 240 COLUMNS = 79 'иначе длина строки равна 79 250 SPACES = SPACES - 1 'отнимаем последний пробел 260 GOTO 340 'идем на вычисление пробелов 270 C$ = MID$(S$,STRINGPTR+1,1) 'проверяем на конец слова 280 IF C$ <> " " THEN 300 'если не пробел, то уход 290 GOTO 340 'иначе на вычисление пробелов 300 COLUMNS = COLUMNS - LASTSPACE 'возвращаемся к концу слова 310 STRINGPTR = STRINGPTR - COLUMNS + 1 'возвращаем указатель 320 COLUMNS = LASTSPACE - 1 'убираем последний пробел 330 SPACES = SPACES - 1 'уменьшаем число пробелов
340 '''вычисляем число точек на пробел 350 EXTRASPACES = 80 - COLUMNS 'вычисляем число пробелов в конце 360 TOTALSPACES = EXTRASPACES + SPACES 'добавляем к пробелам 370 TOTALDOTS = 6*TOTALSPACES 'вычисляем число точек 380 DOTSPERSPC = TOTALDOTS/SPACES 'получаем число точек на пробел 390 EXTRADOTS = TOTALDOTS MOD SPACES 'остаток от деления 400 '''теперь печатаем первую строчку нашего текста 410 OPEN "LPT1:" AS #1 'открываем принтер 420 PRINTPTR = 1 'указатель на начало буфера данных 430 C$ = MID$(S$,PRINTPTR,1) 'берем символ 440 PRINTPTR = PRINTPTR + 1 'увеличиваем указатель 450 IF C$ = " " THEN 500 'если пробел, то на обработку пробела 460 PRINT #1, C$ 'иначе печатаем символ 470 IF PRINTPTR = COLUMNS + 1 THEN 590 'выход по концу строки 480 GOTO 430 'иначе печатаем следующий символ 490 '''вот процедура печати пробелов 500 PRINT #1, CHR$(27) + "K"; 'переход в графический режим 510 NUMBERDOTS = DOTSPERSPC 'вычисляем число байтов ASCII 0 520 IF EXTRADOTS = 0 THEN 550 'если нет добавочных точек, уход 530 NUMBERDOTS = DOTSPERSPC + 1 'иначе добавляем точку 540 EXTRADOTS = EXTRADOTS - 1 'уменьшаем число добавочных точек 550 PRINT #1, CHR$(NUMBERDOTS); 'посылаем число графических байт 560 PRINT #1, CHR$(0); ' 570 FOR N = 1 TO NUMBERDOTS: PRINT #1, CHR$(0): NEXT 580 GOTO 430 'пробел окончен, идем на след. символ 590 PRINT #1, CHR$(13) 'в конце печатаем возврат каретки
Низкий уровень. Соответствующая ассемблерная процедура слишком длинная, чтобы приводить ее здесь. Она работает в точности так же, как и проце- дура на Бейсике, за исключением того, что нет необходимости заво- дить отдельную переменную, чтобы хранить строку. Нужно просто установить указатели на начало и конец строки, которую надо напе- чатать в буфере данных.
|