Summary: | Продвижение нашей системы печати в WINE | ||
---|---|---|---|
Product: | WINE@Etersoft | Reporter: | Виталий Перов <vitperov> |
Component: | Печать ; Диалог печати | Assignee: | Евгений <evcalipt> |
Status: | CLOSED INVALID | QA Contact: | |
Severity: | major | ||
Priority: | P3 | CC: | kondratyuk, lav, olezha |
Version: | 2.0 | Keywords: | TO_WINEHQ |
Target Milestone: | --- | ||
Hardware: | PC | ||
OS: | Linux | ||
Whiteboard: | |||
Заявки RT: | Связано с: | ||
Дата напоминания: | |||
Bug Depends on: | 1686, 2843, 3146, 4111, 6087 | ||
Bug Blocks: | 443, 3000 |
Description
Виталий Перов
2010-09-13 17:16:01 MSD
Для начала нужно реализовать поддержку получения имени принтера через функцию GetJob Написал патч. Отправил. Патч принят. Следующий шаг - реализация поддержки получения структуры DevMode через функцию GetJob. В этом случае всё немного сложнее: 1)Хорошо бы записывать поле DevMode при вызове AddJob (как это сделано с PrinterName). Но проблема в том, что для функции AddJob структура DevMode не доступна. 2)Даже если как-то удастся передать структуру при вызове AddJob, нет гарантии, что на момент вызова EndDoc там будет нужное количество копий. Возможно в процессе формирования задания создаётся промежуточная структура DevMode, в этом случае во внутренней структуре job_t будет ссылка на первую структуру DevMode с незаполненными полями. Надо проверить возможность такого варианта DevMode можно получать из структуры PRINTER_INFO_2 с помощью GetPrinter. Но, как написано в баге 4111, к моменту отправки задания на печать DevMode, который мы получаем относится не к конкретному заданию, а скорее к это к настройкам по умолчанию, и извлечь оттуда необходимые параметры не удаётся. Надо проверить что мы получим при вызове GetPrinter из AddJob, возможно в этом случае структура будет относится именно к текущему заданию. Проверил. GetPrinter проверяет есть ли структуру DevMode в реестре, если нет, то возвращает структуру по умолчанию. Для этого вызывается функция WINSPOOL_GetDefaultDevMode. Таким образом, через GetPrinter ничего полезного не получить. Из PSDRV_StartDocA вызывается StartDocPrinter, из которого вызывается AddJob. В функции PSDRV_StartDocA доступна структура PSDRV_PDEVICE, где находится правильный DevMode. Передать её в AddJob нет никакой возможности. К внутренним структурам job_t и printer_t из PSDRV_StartDocA тоже не достучаться. Возможно из PSDRV_StartDocA вызывать SetJob, и таким образом сохранять значение DevMode, но на первый взгляд выглядит немного кривовато... Самым правильным решением было бы написать тест на функцию AddJob, а затем вызвать GetJob и проверить заполняет ли винда поле DevMode. Затем, вторым тестом проверить добавляется ли DevMode после вызова PSDRV_StartDocA. Если изначально DevMode отсутствует, но при вызове PSDRV_StartDocA присутствует, значит предложенный алгоритм правильный. Начал писать тест. Оказалось всё немного по-другому. Функция AddJobW не получает структуру JOB_INFO_1, а наоборот - возвращает заполненную. Последующее заполнение полей структуры делается при помощи SetJob (заполняется только поле с именем документа, всё остальное - нули) Написал простой тест: Сначала вызывается AddJob, затем вызывается GetJob. Поля структуры на винде: pPrinterName - непонятная строка 'Hy$' pMachineName = Null pUserName - не Null, но при обращении происходит падение pDocumentName = Null pDevMode = Null Написал тест на функцию StartDocPrinter. После её вызова GetJob возвращает: Результаты в wine: info.c:2946: job_id = 2 info.c:2952: ------------------ info.c:2953: printer_name='hp' info.c:2954: machine_name='(null)' info.c:2955: user_name='(null)' info.c:2956: document_name='winetest' info.c:2957: DevMode='0' На винде: info.c:2928: default_printer: 'Microsoft XPS Document Writer' info.c:2946: job_id = 15 info.c:2952: ------------------ info.c:2953: printer_name='Microsoft XPS Document Writer' info.c:2954: machine_name='\\WINXPOFFICE' info.c:2955: user_name='└фьшэшёЄЁрЄюЁ' info.c:2956: document_name='winetest' info.c:2957: DevMode='2420608' Т.е заполнение имени принтера и DevMode происходит именно внутри StartDocPrinter Написанный тест скорее всего отправить не получится т.к он оставляет после себя следы: Задание добавляется, но никак не удаляется. Для удаления задания нет специальной функции, задание само должно удалятся после отправки на печать. Ещё одно возможное решение - вызов функции DocumentPropertiesA. Она получает DevMode напрямую из драйвера gdi32. Проблема в том, что функция возвращает саму структуру, а не указатель на неё. т.е в функции ScheduleJob для печати через lpr можно получить структуру DevMode, но сделать так, указатель на структуру был бы доступен через GetJob - наверное не получится. Как вариант - вызывать DocumentPropertiesA из GetJob, при этом получить полную структуру DEVMODE, и дописать её к концу структуры JOB_INFO_2. Ещё замечания по поводу SetJob. Функции передаётся указатель на DevMode, но не известно где лежит сама структура: возможно она также дописывается к концу JOB_INFO_2, и в это случае SetJob обязана её копировать. Надо проверить в винде. Проверил в винде: структура, действительно хранится внутри выделяемого буфера. Реализовал поддержу pDevMode в SetJob и GetJob. Перед отправкой патча хотелось бы его проверить вместе с патчем к баге #4111 Проверил. Работает. Патч отправил. Следующая проверка на винде: С помощью SetJob установить pDevMode = NULL; Затем прочитать полученное значение с помощью GetJob. Возможно винда всё-таки возвращает DevMode в этом случае (In reply to comment #14) > Проверил. Работает. Патч отправил. > Переделал патч. Проверил совместно с патчем 4111. При печати происходит падение. Где-то ошибка Переделал. Проверил. Отправил. Патч не принимают. Можно пока зайти с другой стороны - посмотреть отличие наших диалогов печати от диалогов в официальном релизе. Там тоже должны быть исправления, касающиеся количества копий и раскладки по копиям. Наши патчи в printdlg.c: 1) 19adc737 (Константин Кондратюк 2008-04-08 comdlg32: Fix eterbugs #225, #985 - завёл отдельную багу №6087 2) 1af0303e (Vitaly Perov 2009-05-24 14:58:14 comdlg32/printdlg: Let printer manage multiple copies if it can (fix duplex printing) (eterbugs #1686 and #3146) 3) 312c1f3c (Vitaly Perov 2009-07-08 18:20:15 4) 90197619 (Vitaly Lipatov 2009-02-11 Some changes for print dialog Из них к дуплексу и разбивке по копиям относятся патчи 2 и 3. Хотелось бы как-то объединить патчи 2 и 3. Один для функции PRINTDLG_UpdatePrintDlgA, другой для W. Общую часть - определение возможности принтера печатать много копий хотелось бы вынести в отдельную функцию. Проверил. Написать универсальную функцию не получится. Придётся дублировать. В нашем патче количество поддерживаемых копий определяется с помощью вызова DeviceCapabilities. В коде winehq для этого используется конструкция if (lpdm->dmFields & DM_COPIES. Надо проверить работает ли это у нас, если да, то это существенно упрощает патч. Ещё один нехороший момент: Патч направлен на то, чтобы по умолчанию драйвер принтера занимался дуплексом, формированием нужного количества копий и разбивкой. В winehq по умолчанию это делает приложение. Соответственно возникают проблемы с разбивкой по копиям: Раньше в некоторых приложениях это работало (за счёт того, что разбивку поддерживало приложение), после принятия патча она работать перестанет. Решением проблемы будет - исправить настройки принтера по умолчанию так, чтобы он возвращал, что он умеет производить разбивку по копиям. Сделал патч для PRINTDLG_UpdatePrintDlgA. В блокноте вызывается W-функция. Проверял в 1с80. Для печати используется драйвер принтера, но разбивка по копиям не работает Пробовал wine --removeprinters - не помогло. Согласно баге #2843 работать и не должно. Поддержка разбивки появилась у нас только тогда, когда мы начали использовать опции команды lpr. Видимо придётся делать всё одним большим патчем: сразу исправлять порядок обработки в printdlg и сразу добавлять опции комманды lpr. В winehq нашёл только одну багу, относящуюся к раскладке по копиям и дуплексу: http://bugs.winehq.org/show_bug.cgi?id=23634 Судя по обсуждению никто не знает как на самом деле работает наша система печати, но все видят, что она работает. lpr - обёртка, ссылающаяся на lpr-cups, которая использует всё те же функции библиотеки cups. Поступило предложение вместо lpr функции библиотеки cups. Когда-то пробовал печатать через функции cups - всё работало, но не поддерживался дуплекс и разбивка по копиям. Можно попробовать посмотреть в исходниках lpr-cups как парсятся параметры командной строки, и как задаются необходимые опции. Исходники можно взять на: 1)/srv/lav/Projects/git-alt/other-owners/cups 2)http://sisyphus.ru/ru/srpm/Sisyphus/cups/gear 3)http://git.altlinux.org/gears/c/cups.git Нашёл исходники. Парсингом занимается функция cupsParseOptions. Она доступна и в wine Проверил. Не работает. Добавляются 2 опции, но при печати они почему-то не работают. Возможно потому, что в опциях стоит одна копия. А нужное количество задано внутри выходного файла. Теперь всё работает. Думаю первым делом нужно отправить патч, который убирает выставление нужного количества копий внутри PostScript файла, и переносит это на этап отправки задания. Сделал патч. Проверил. Пока не работает. Почему-то GetJobW не может получить структуру DEVMODE, из которой берётся нужное количество копий. Разобрался. GetJobW сначала требует одного количества байт, а затем уже другого: fixme:winspool:ScheduleJob needed = 366 trace:winspool:get_job_info 0x1 2 2 0x20a898 366 0x32def8 fixme:winspool:get_job_info_2 Devmode found fixme:winspool:get_job_info_2 Devmode is to be copied fixme:winspool:ScheduleJob needed = 368 поэтому запись в выделенный буфер не происходит. Виновато выравнивание. Думаю в случае отсутствия указателя на буфер следует возвращать максимально возможное количество байт (с учётом максимального выравнивания) выравнивание добавлял по примеру внутренней функции convert_printerinfo_W_to_A. Эта функция не сообщает о длине требуемого буфера, поэтому этот код работает. Надо сделать тес и посмотреть на винде: есть выравнивание или нет. Если есть, то при запросе размера выделять больший размер. Проверил. В винде выравнивание есть. Сделал патч, исправляющий ошибку. Отправил в winehq. Проверил предыдущий патч (через LPR:). Всё работает! На всякий случай следует ещё проверить через CUPS: Патч был приложен не к тому месту, поэтому и правда был бесполезен. Непонятно почему так получилось, ведь патч проверялся: без него бага была, а с ним исчезала. Переделал патч. Отправил в Winehq Дополнил патч. Отправил повторно Отправил повторно первый патч, исправляющий увеличение указателя. Переделал патч. Теперь выравнивание происходит не относительно значения указателя, а относительно начала данных. Таким образом, значение выравнивания никак не зависит от передаваемого адреса буфера. Отправил патч в winehq. Посмотрел статус патча на http://source.winehq.org/patches/ Патч требует тестов. Для написания теста можно воспользоваться последовательностью вызовов из StartDocPrinterW. Начал реализовывать Откладываем, на bugs@lists.etersoft.ru не должно висеть багов. Выяснилось, что текущая наша система печати имеет проблемы. https://bugs.etersoft.ru/show_bug.cgi?id=9230 Откладываем задачи, к которым не обращались более 100 дней. Задача по релизу W@E 2.0 Уже давно не актуально, аннулирую. |