Справочник программиста на персональном компьютере фирмы IBM. Принтер - Выравнивание правого поля
ОГЛАВЛЕНИЕ
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) 'в конце печатаем возврат каретки
Низкий уровень.
Соответствующая ассемблерная процедура слишком длинная, чтобы
приводить ее здесь. Она работает в точности так же, как и проце-
дура на Бейсике, за исключением того, что нет необходимости заво-
дить отдельную переменную, чтобы хранить строку. Нужно просто
установить указатели на начало и конец строки, которую надо напе-
чатать в буфере данных.