Справочник программиста на персональном компьютере фирмы IBM. Принтер
Страница 17. Выравнивание правого поля


     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)    'в конце печатаем возврат каретки

   Низкий уровень.


   Соответствующая ассемблерная процедура слишком длинная,  чтобы
приводить ее здесь. Она работает  в точности так же, как и проце-
дура на Бейсике, за исключением того, что нет необходимости заво-
дить отдельную переменную,  чтобы  хранить  строку.  Нужно просто
установить указатели на начало и конец строки, которую надо напе-
чатать в буфере данных.


 
« Предыдущая статья   Следующая статья »