Coverage for pyilper/pilhp82162a.py: 86%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1391 statements  

1#!/usr/bin/python3 

2# -*- coding: utf-8 -*- 

3# pyILPER 1.2.4 for Linux 

4# 

5# An emulator for virtual HP-IL devices for the PIL-Box 

6# derived from ILPER 1.4.5 for Windows 

7# Copyright (c) 2008-2013 Jean-Francois Garnier 

8# C++ version (c) 2013 Christoph Gießelink 

9# Python Version (c) 2015 Joachim Siebold 

10# HP82162a printer emulation derived from the nonpareil emulator 

11# (C) 1995, 2003, 2004, 2005, 2006, 2008 Eric Smith 

12# 

13# This program is free software; you can redistribute it and/or 

14# modify it under the terms of the GNU General Public License 

15# as published by the Free Software Foundation; either version 2 

16# of the License, or (at your option) any later version. 

17# 

18# This program is distributed in the hope that it will be useful, 

19# but WITHOUT ANY WARRANTY; without even the implied warranty of 

20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

21# GNU General Public License for more details. 

22# 

23# You should have received a copy of the GNU General Public License 

24# along with this program; if not, write to the Free Software 

25# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 

26# 

27# HP82162A virtual device classes --------------------------------------------- 

28# 

29# Changelog 

30# 05.08.2017 jsi: 

31# - initial version 

32# 20.08.2017 jsi: 

33# - fixed: papersize for pdf output not configurable 

34# 21.08.2017 jsi: 

35# - refactoring: new pdf printer class used 

36# - store number of pdf columns in system configuration 

37# - disable gui if device not enabled 

38# 27.08.2017 jsi: 

39# - removed redraw timer: not needed 

40# - resize of printer tab now repositions everything correctly 

41# 28.08.2017 jsi: 

42# - remove alignments from GUI 

43# - get papersize config parameter in constructor of tab widget 

44# 03.09.2017 jsi 

45# - register pildevice is now method of commobject 

46# 16.09.2017 jsi 

47# - added missing entries in ASCII character table 

48# 19.09.2017 jsi 

49# - use raw strings in re.findall 

50# 19.09.2017 jsi 

51# - use raw strings in re.findall 

52# 24.09.2016 jsi 

53# - added mouse wheel scrolling support 

54# 02.12.2017 jsi 

55# - on the fly reconfiguration of the pixelsize 

56# - fix: keep scroll position on resize 

57# 04.01.2018 jsi 

58# - reconfigure log check box object 

59# - flush log buffer  

60# 16.01.2018 jsi 

61# - adapt to cls_tabgeneric, implemented cascading config menu 

62# 20.01.2018 jsi 

63# - the pixel size is now a dual parameter 

64# 28.01.2018 jsi 

65# - set AutoDefault property of buttons to false 

66# 29.01.2018 jsi 

67# - shrink all parent widgets if the pixel size was changed 

68# 22.02.2018 jsi 

69# - disabled shrinking parent widgets becaus of errors on reconfiguration 

70# 

71import copy 

72import queue 

73import threading 

74import re 

75from PySide6 import QtCore, QtWidgets 

76from .pilcore import UPDATE_TIMER, PDF_ORIENTATION_PORTRAIT 

77from .pilconfig import PILCONFIG 

78from .pilcharconv import charconv, CHARSET_HP41, CHARSET_ROMAN8 

79from .pildevbase import cls_pildevbase 

80from .pilwidgets import cls_tabgeneric, LogCheckboxWidget, T_INTEGER, O_DEFAULT 

81from .pilpdf import cls_pdfprinter 

82from .pilcore import HP82162A_LINEBUFFERSIZE 

83 

84# 

85# constants -------------------------------------------------------------- 

86# 

87PRINTER_CHARACTER_WIDTH_PIXELS= 7 

88PRINTER_WIDTH_CHARS= 24 

89PRINTER_WIDTH= (PRINTER_WIDTH_CHARS * PRINTER_CHARACTER_WIDTH_PIXELS) 

90PRINTER_CHARACTER_HEIGHT_PIXELS= 13 

91DISPLAY_LINE_SPACING=0 

92 

93PDF_LINES=70 # number of lines in pdf output 

94PDF_MARGINS=50 # margins (top,bot,left,right) of pdf output 

95PDF_MAX_COLS=3 # max number of columns in pdf output 

96PDF_COLUMN_SPACING=80 # spacing between columns 

97PDF_LINE_SPACING=0 # linespacing in (relative) pixel 

98 

99# 

100# printer modeswitch 

101# 

102MODESWITCH_MAN=0 

103MODESWITCH_TRACE=1 

104MODESWITCH_NORM=2 

105 

106# HP-IL Status bits 

107STA_SR= 64 

108STA_MB= 32 

109STA_MA= 16 

110STA_ER= 8 

111STA_PA= 4 

112STA_PR= 2 

113STA_LA= 1 

114 

115STA_EL= 128 << 8 

116STA_ID= 64 << 8 

117STA_BE= 32 << 8 

118STA_EB= 16 << 8 

119STA_RJ= 8 << 8 

120STA_DW= 4 << 8 

121STA_CO= 2 << 8 

122STA_LC= 1 << 8 

123 

124# Printer status bits 

125mode_8bit= 1 

126mode_lowercase= 2 

127mode_doublewide= 4 

128mode_column= 8 

129mode_rjust= 16 

130mode_parse= 32 

131mode_barcode= 64 

132mode_inhibit_advance= 128 

133 

134# 

135# printer buffer data types 

136# 

137type_char= 1 

138type_column= 2 

139type_barcode= 3 

140type_format= 4 

141type_skip= 5 

142 

143# GUI commands 

144CMD_MAN= 0 

145CMD_NORM= 1 

146CMD_TRACE= 2 

147CMD_PRINT_PRESSED= 3 

148CMD_ADV_PRESSED= 4 

149CMD_CLEAR= 5 

150CMD_PRINT_RELEASED= 6 

151CMD_ADV_RELEASED= 7 

152 

153# HPIL-Thread commands 

154REMOTECMD_CLEAR=0 

155REMOTECMD_PRINT=1 

156REMOTECMD_LOG=2 

157 

158# 

159# charsets 

160# 

161CHARSET_ASCII=0 

162CHARSET_ALTERNATE=1 

163# 

164# hp82162a character generator ------------------------------------------------- 

165# character codes taken from the nonpareil calculator simulator 

166# (C) Eric Smith 

167# 

168 

169class hp82162a_char(object): 

170 

171 def __init__(self): 

172 super().__init__() 

173# 

174# ASCII charset 

175# 

176 self.ac= { } 

177 self.ac[0x00] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

178 self.ac[0x01] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

179 self.ac[0x02] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

180 self.ac[0x03] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

181 self.ac[0x04] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

182 self.ac[0x05] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

183 self.ac[0x06] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

184 self.ac[0x07] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

185 self.ac[0x08] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

186 self.ac[0x09] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

187 self.ac[0x0a] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

188 self.ac[0x0b] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

189 self.ac[0x0c] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

190 self.ac[0x0d] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

191 self.ac[0x0e] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

192 self.ac[0x0f] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

193 self.ac[0x10] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

194 self.ac[0x11] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

195 self.ac[0x12] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

196 self.ac[0x13] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

197 self.ac[0x14] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

198 self.ac[0x15] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

199 self.ac[0x16] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

200 self.ac[0x17] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

201 self.ac[0x18] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

202 self.ac[0x19] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

203 self.ac[0x1A] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

204 self.ac[0x1B] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

205 self.ac[0x1C] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

206 self.ac[0x1D] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

207 self.ac[0x1E] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

208 self.ac[0x1F] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) 

209 self.ac[0x20] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) # space 

210 self.ac[0x21] = bytes([ 0x00, 0x00, 0x5f, 0x00, 0x00 ]) # bang 

211 self.ac[0x22] = bytes([ 0x00, 0x03, 0x00, 0x03, 0x00 ]) # double quote 

212 self.ac[0x23] = bytes([ 0x14, 0x7f, 0x14, 0x7f, 0x14 ]) # hash (pound, octothorpe) 

213 self.ac[0x24] = bytes([ 0x24, 0x2a, 0x7f, 0x2a, 0x12 ]) # dollar 

214 self.ac[0x25] = bytes([ 0x23, 0x13, 0x08, 0x64, 0x62 ]) # percent 

215 self.ac[0x26] = bytes([ 0x36, 0x49, 0x56, 0x20, 0x50 ]) # ampersand 

216 self.ac[0x27] = bytes([ 0x00, 0x00, 0x03, 0x00, 0x00 ]) # single quote 

217 self.ac[0x28] = bytes([ 0x00, 0x1c, 0x22, 0x41, 0x00 ]) # left parenthesis 

218 self.ac[0x29] = bytes([ 0x00, 0x41, 0x22, 0x1c, 0x00 ]) # right parenthesis 

219 self.ac[0x2a] = bytes([ 0x14, 0x08, 0x3e, 0x08, 0x14 ]) # asterisk 

220 self.ac[0x2b] = bytes([ 0x08, 0x08, 0x3e, 0x08, 0x08 ]) # plus 

221 self.ac[0x2c] = bytes([ 0x00, 0x40, 0x30, 0x00, 0x00 ]) # comma 

222 self.ac[0x2d] = bytes([ 0x08, 0x08, 0x08, 0x08, 0x08 ]) # hyphen 

223 self.ac[0x2e] = bytes([ 0x00, 0x60, 0x60, 0x00, 0x00 ]) # period 

224 self.ac[0x2f] = bytes([ 0x20, 0x10, 0x08, 0x04, 0x02 ]) # slash 

225 self.ac[0x30] = bytes([ 0x3e, 0x51, 0x49, 0x45, 0x3e ]) # zero 

226 self.ac[0x31] = bytes([ 0x00, 0x42, 0x7f, 0x40, 0x00 ]) # one 

227 self.ac[0x32] = bytes([ 0x62, 0x51, 0x49, 0x49, 0x46 ]) # two 

228 self.ac[0x33] = bytes([ 0x21, 0x41, 0x49, 0x4d, 0x33 ]) # three 

229 self.ac[0x34] = bytes([ 0x18, 0x14, 0x12, 0x7f, 0x10 ]) # four 

230 self.ac[0x35] = bytes([ 0x27, 0x45, 0x45, 0x45, 0x39 ]) # five 

231 self.ac[0x36] = bytes([ 0x3c, 0x4a, 0x49, 0x48, 0x30 ]) # six 

232 self.ac[0x37] = bytes([ 0x01, 0x71, 0x09, 0x05, 0x03 ]) # seven 

233 self.ac[0x38] = bytes([ 0x36, 0x49, 0x49, 0x49, 0x36 ]) # eight 

234 self.ac[0x39] = bytes([ 0x06, 0x49, 0x49, 0x29, 0x1e ]) # nine 

235 self.ac[0x3a] = bytes([ 0x00, 0x00, 0x24, 0x00, 0x00 ]) # colon 

236 self.ac[0x3b] = bytes([ 0x00, 0x40, 0x34, 0x00, 0x00 ]) # semicolon 

237 self.ac[0x3c] = bytes([ 0x08, 0x14, 0x22, 0x41, 0x00 ]) # less than 

238 self.ac[0x3d] = bytes([ 0x14, 0x14, 0x14, 0x14, 0x14 ]) # equal 

239 self.ac[0x3e] = bytes([ 0x00, 0x41, 0x22, 0x14, 0x08 ]) # greater than 

240 self.ac[0x3f] = bytes([ 0x02, 0x01, 0x51, 0x09, 0x06 ]) # question mark 

241 self.ac[0x40] = bytes([ 0x3e, 0x41, 0x5d, 0x5d, 0x1e ]) # at 

242 self.ac[0x41] = bytes([ 0x7e, 0x11, 0x11, 0x11, 0x7e ]) # UC A 

243 self.ac[0x42] = bytes([ 0x7f, 0x49, 0x49, 0x49, 0x36 ]) # UC B 

244 self.ac[0x43] = bytes([ 0x3e, 0x41, 0x41, 0x41, 0x22 ]) # UC C 

245 self.ac[0x44] = bytes([ 0x41, 0x7f, 0x41, 0x41, 0x3e ]) # UC D 

246 self.ac[0x45] = bytes([ 0x7f, 0x49, 0x49, 0x49, 0x41 ]) # UC E 

247 self.ac[0x46] = bytes([ 0x7f, 0x09, 0x09, 0x09, 0x01 ]) # UC F 

248 self.ac[0x47] = bytes([ 0x3e, 0x41, 0x41, 0x51, 0x72 ]) # UC G 

249 self.ac[0x48] = bytes([ 0x7f, 0x08, 0x08, 0x08, 0x7f ]) # UC H 

250 self.ac[0x49] = bytes([ 0x00, 0x41, 0x7f, 0x41, 0x00 ]) # UC I 

251 self.ac[0x4a] = bytes([ 0x20, 0x40, 0x40, 0x40, 0x3f ]) # UC J 

252 self.ac[0x4b] = bytes([ 0x7f, 0x08, 0x14, 0x22, 0x41 ]) # UC K 

253 self.ac[0x4c] = bytes([ 0x7f, 0x40, 0x40, 0x40, 0x40 ]) # UC L 

254 self.ac[0x4d] = bytes([ 0x7f, 0x02, 0x0c, 0x02, 0x7f ]) # UC M 

255 self.ac[0x4e] = bytes([ 0x7f, 0x04, 0x08, 0x10, 0x7f ]) # UC N 

256 self.ac[0x4f] = bytes([ 0x3e, 0x41, 0x41, 0x41, 0x3e ]) # UC O 

257 self.ac[0x50] = bytes([ 0x7f, 0x09, 0x09, 0x09, 0x06 ]) # UC P 

258 self.ac[0x51] = bytes([ 0x3e, 0x41, 0x51, 0x21, 0x5e ]) # UC Q 

259 self.ac[0x52] = bytes([ 0x7f, 0x09, 0x19, 0x29, 0x46 ]) # UC R 

260 self.ac[0x53] = bytes([ 0x26, 0x49, 0x49, 0x49, 0x32 ]) # UC S 

261 self.ac[0x54] = bytes([ 0x01, 0x01, 0x7f, 0x01, 0x01 ]) # UC T 

262 self.ac[0x55] = bytes([ 0x3f, 0x40, 0x40, 0x40, 0x3f ]) # UC U 

263 self.ac[0x56] = bytes([ 0x07, 0x18, 0x60, 0x18, 0x07 ]) # UC V 

264 self.ac[0x57] = bytes([ 0x7f, 0x20, 0x18, 0x20, 0x7f ]) # UC W 

265 self.ac[0x58] = bytes([ 0x63, 0x14, 0x08, 0x14, 0x63 ]) # UC X 

266 self.ac[0x59] = bytes([ 0x03, 0x04, 0x78, 0x04, 0x03 ]) # UC Y 

267 self.ac[0x5a] = bytes([ 0x61, 0x51, 0x49, 0x45, 0x43 ]) # UC Z 

268 self.ac[0x5b] = bytes([ 0x00, 0x7f, 0x41, 0x41, 0x00 ]) # left bracket 

269 self.ac[0x5c] = bytes([ 0x02, 0x04, 0x08, 0x10, 0x20 ]) # backslash 

270 self.ac[0x5d] = bytes([ 0x00, 0x41, 0x41, 0x7f, 0x00 ]) # right bracket 

271 self.ac[0x5e] = bytes([ 0x04, 0x02, 0x01, 0x02, 0x04 ]) # ^ 

272 self.ac[0x5f] = bytes([ 0x40, 0x40, 0x40, 0x40, 0x40 ]) # underscore 

273 self.ac[0x60] = bytes([ 0x00, 0x01, 0x02, 0x04, 0x00 ]) # ` 

274 self.ac[0x61] = bytes([ 0x20, 0x54, 0x54, 0x54, 0x78 ]) # LC a 

275 self.ac[0x62] = bytes([ 0x7f, 0x48, 0x44, 0x44, 0x38 ]) # LC b 

276 self.ac[0x63] = bytes([ 0x38, 0x44, 0x44, 0x44, 0x20 ]) # LC c 

277 self.ac[0x64] = bytes([ 0x38, 0x44, 0x44, 0x48, 0x7f ]) # LC d 

278 self.ac[0x65] = bytes([ 0x38, 0x54, 0x54, 0x54, 0x08 ]) # LC e 

279 self.ac[0x66] = bytes([ 0x08, 0x7c, 0x0a, 0x01, 0x02 ]) # LC f 

280 self.ac[0x67] = bytes([ 0x08, 0x14, 0x54, 0x54, 0x38 ]) # LC g 

281 self.ac[0x68] = bytes([ 0x7f, 0x10, 0x08, 0x08, 0x70 ]) # LC h 

282 self.ac[0x69] = bytes([ 0x00, 0x44, 0x7d, 0x40, 0x00 ]) # LC i 

283 self.ac[0x6a] = bytes([ 0x20, 0x40, 0x40, 0x3d, 0x00 ]) # LC j 

284 self.ac[0x6b] = bytes([ 0x00, 0x7f, 0x28, 0x44, 0x00 ]) # LC k 

285 self.ac[0x6c] = bytes([ 0x00, 0x41, 0x7f, 0x40, 0x00 ]) # LC l 

286 self.ac[0x6d] = bytes([ 0x78, 0x04, 0x18, 0x04, 0x78 ]) # LC m 

287 self.ac[0x6e] = bytes([ 0x7c, 0x08, 0x04, 0x04, 0x78 ]) # LC n 

288 self.ac[0x6f] = bytes([ 0x38, 0x44, 0x44, 0x44, 0x38 ]) # LC o 

289 self.ac[0x70] = bytes([ 0x7c, 0x14, 0x24, 0x24, 0x18 ]) # LC p 

290 self.ac[0x71] = bytes([ 0x18, 0x24, 0x24, 0x7c, 0x40 ]) # LC q 

291 self.ac[0x72] = bytes([ 0x7c, 0x08, 0x04, 0x04, 0x08 ]) # LC r 

292 self.ac[0x73] = bytes([ 0x48, 0x54, 0x54, 0x54, 0x24 ]) # LC s 

293 self.ac[0x74] = bytes([ 0x04, 0x3e, 0x44, 0x20, 0x00 ]) # LC t 

294 self.ac[0x75] = bytes([ 0x3c, 0x40, 0x40, 0x20, 0x7c ]) # LC u 

295 self.ac[0x76] = bytes([ 0x1c, 0x20, 0x40, 0x20, 0x1c ]) # LC v 

296 self.ac[0x77] = bytes([ 0x3c, 0x40, 0x30, 0x40, 0x3c ]) # LC w 

297 self.ac[0x78] = bytes([ 0x44, 0x28, 0x10, 0x28, 0x44 ]) # LC x 

298 self.ac[0x79] = bytes([ 0x44, 0x28, 0x10, 0x08, 0x04 ]) # LC y 

299 self.ac[0x7a] = bytes([ 0x44, 0x64, 0x54, 0x4c, 0x44 ]) # LC z 

300 self.ac[0x7b] = bytes([ 0x00, 0x08, 0x36, 0x41, 0x00 ]) # { 

301 self.ac[0x7c] = bytes([ 0x00, 0x00, 0x7f, 0x00, 0x00 ]) # | 

302 self.ac[0x7d] = bytes([ 0x00, 0x41, 0x36, 0x08, 0x00 ]) #  

303 self.ac[0x7e] = bytes([ 0x02, 0x01, 0x02, 0x04, 0x02 ]) # ~ 

304 self.ac[0x7f] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) #  

305 

306# 

307# alternate characterset 

308# 

309 self.hc= { } 

310 self.hc[0x00] = bytes([ 0x08, 0x1c, 0x3e, 0x1c, 0x08 ]) # diamond 

311 self.hc[0x01] = bytes([ 0x00, 0x14, 0x08, 0x14, 0x00 ]) # small x 

312 self.hc[0x02] = bytes([ 0x44, 0x29, 0x11, 0x29, 0x44 ]) # x-bar 

313 self.hc[0x03] = bytes([ 0x08, 0x1c, 0x2a, 0x08, 0x08 ]) # left arrow 

314 self.hc[0x04] = bytes([ 0x38, 0x44, 0x44, 0x38, 0x44 ]) # LC alpha 

315 self.hc[0x05] = bytes([ 0x7e, 0x15, 0x25, 0x25, 0x1a ]) # UC beta 

316 self.hc[0x06] = bytes([ 0x7f, 0x01, 0x01, 0x01, 0x03 ]) # UC gamma 

317 self.hc[0x07] = bytes([ 0x10, 0x30, 0x7f, 0x30, 0x10 ]) # down arrow 

318 self.hc[0x08] = bytes([ 0x60, 0x18, 0x06, 0x18, 0x60 ]) # UC delta 

319 self.hc[0x09] = bytes([ 0x38, 0x44, 0x44, 0x3c, 0x04 ]) # LC sigma 

320 self.hc[0x0a] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) # nothing (LF) 

321 self.hc[0x0b] = bytes([ 0x62, 0x14, 0x08, 0x10, 0x60 ]) # LC lambda 

322 self.hc[0x0c] = bytes([ 0x40, 0x3c, 0x20, 0x20, 0x1c ]) # LC mu 

323 self.hc[0x0d] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) # nothing (CR) 

324 self.hc[0x0e] = bytes([ 0x10, 0x18, 0x78, 0x04, 0x02 ]) # LC tau 

325 self.hc[0x0f] = bytes([ 0x08, 0x55, 0x77, 0x55, 0x08 ]) # UC phi 

326 self.hc[0x10] = bytes([ 0x3e, 0x49, 0x49, 0x49, 0x3e ]) # UC theta 

327 self.hc[0x11] = bytes([ 0x5e, 0x61, 0x01, 0x61, 0x5e ]) # UC omega 

328 self.hc[0x12] = bytes([ 0x30, 0x4a, 0x4d, 0x49, 0x30 ]) # LC delta 

329 self.hc[0x13] = bytes([ 0x78, 0x14, 0x15, 0x14, 0x78 ]) # UC A dot 

330 self.hc[0x14] = bytes([ 0x38, 0x44, 0x45, 0x3e, 0x44 ]) # LC a dot 

331 self.hc[0x15] = bytes([ 0x78, 0x15, 0x14, 0x15, 0x78 ]) # UC A umlaut 

332 self.hc[0x16] = bytes([ 0x38, 0x45, 0x44, 0x7d, 0x40 ]) # LC a umlaut 

333 self.hc[0x17] = bytes([ 0x3c, 0x43, 0x42, 0x43, 0x3c ]) # UC O umlaut 

334 self.hc[0x18] = bytes([ 0x38, 0x45, 0x44, 0x45, 0x38 ]) # LC o umlaut 

335 self.hc[0x19] = bytes([ 0x3e, 0x41, 0x40, 0x41, 0x3e ]) # UC U umlaut 

336 self.hc[0x1a] = bytes([ 0x3c, 0x41, 0x40, 0x41, 0x3c ]) # LC u umlaut 

337 self.hc[0x1b] = bytes([ 0x7e, 0x09, 0x7f, 0x49, 0x49 ]) # UC AE 

338 self.hc[0x1c] = bytes([ 0x38, 0x44, 0x38, 0x54, 0x58 ]) # LC ae 

339 self.hc[0x1d] = bytes([ 0x14, 0x34, 0x1c, 0x16, 0x14 ]) # not equal 

340 self.hc[0x1e] = bytes([ 0x48, 0x7e, 0x49, 0x41, 0x22 ]) # pound sterling 

341 self.hc[0x1f] = bytes([ 0x55, 0x2a, 0x55, 0x2a, 0x55 ]) # ? 

342 self.hc[0x20] = bytes([ 0x00, 0x00, 0x00, 0x00, 0x00 ]) # space 

343 self.hc[0x21] = bytes([ 0x00, 0x00, 0x5f, 0x00, 0x00 ]) # bang 

344 self.hc[0x22] = bytes([ 0x00, 0x03, 0x00, 0x03, 0x00 ]) # double quote 

345 self.hc[0x23] = bytes([ 0x14, 0x7f, 0x14, 0x7f, 0x14 ]) # hash (pound, octothorpe) 

346 self.hc[0x24] = bytes([ 0x24, 0x2a, 0x7f, 0x2a, 0x12 ]) # dollar 

347 self.hc[0x25] = bytes([ 0x23, 0x13, 0x08, 0x64, 0x62 ]) # percent 

348 self.hc[0x26] = bytes([ 0x36, 0x49, 0x56, 0x20, 0x50 ]) # ampersand 

349 self.hc[0x27] = bytes([ 0x00, 0x00, 0x03, 0x00, 0x00 ]) # single quote 

350 self.hc[0x28] = bytes([ 0x00, 0x1c, 0x22, 0x41, 0x00 ]) # left parenthesis 

351 self.hc[0x29] = bytes([ 0x00, 0x41, 0x22, 0x1c, 0x00 ]) # right parenthesis 

352 self.hc[0x2a] = bytes([ 0x14, 0x08, 0x3e, 0x08, 0x14 ]) # asterisk 

353 self.hc[0x2b] = bytes([ 0x08, 0x08, 0x3e, 0x08, 0x08 ]) # plus 

354 self.hc[0x2c] = bytes([ 0x00, 0x40, 0x30, 0x00, 0x00 ]) # comma 

355 self.hc[0x2d] = bytes([ 0x08, 0x08, 0x08, 0x08, 0x08 ]) # hyphen 

356 self.hc[0x2e] = bytes([ 0x00, 0x60, 0x60, 0x00, 0x00 ]) # period 

357 self.hc[0x2f] = bytes([ 0x20, 0x10, 0x08, 0x04, 0x02 ]) # slash 

358 self.hc[0x30] = bytes([ 0x3e, 0x51, 0x49, 0x45, 0x3e ]) # zero 

359 self.hc[0x31] = bytes([ 0x00, 0x42, 0x7f, 0x40, 0x00 ]) # one 

360 self.hc[0x32] = bytes([ 0x62, 0x51, 0x49, 0x49, 0x46 ]) # two 

361 self.hc[0x33] = bytes([ 0x21, 0x41, 0x49, 0x4d, 0x33 ]) # three 

362 self.hc[0x34] = bytes([ 0x18, 0x14, 0x12, 0x7f, 0x10 ]) # four 

363 self.hc[0x35] = bytes([ 0x27, 0x45, 0x45, 0x45, 0x39 ]) # five 

364 self.hc[0x36] = bytes([ 0x3c, 0x4a, 0x49, 0x48, 0x30 ]) # six 

365 self.hc[0x37] = bytes([ 0x01, 0x71, 0x09, 0x05, 0x03 ]) # seven 

366 self.hc[0x38] = bytes([ 0x36, 0x49, 0x49, 0x49, 0x36 ]) # eight 

367 self.hc[0x39] = bytes([ 0x06, 0x49, 0x49, 0x29, 0x1e ]) # nine 

368 self.hc[0x3a] = bytes([ 0x00, 0x00, 0x24, 0x00, 0x00 ]) # colon 

369 self.hc[0x3b] = bytes([ 0x00, 0x40, 0x34, 0x00, 0x00 ]) # semicolon 

370 self.hc[0x3c] = bytes([ 0x08, 0x14, 0x22, 0x41, 0x00 ]) # less than 

371 self.hc[0x3d] = bytes([ 0x14, 0x14, 0x14, 0x14, 0x14 ]) # equal 

372 self.hc[0x3e] = bytes([ 0x00, 0x41, 0x22, 0x14, 0x08 ]) # greater than 

373 self.hc[0x3f] = bytes([ 0x02, 0x01, 0x51, 0x09, 0x06 ]) # question mark 

374 self.hc[0x40] = bytes([ 0x3e, 0x41, 0x5d, 0x5d, 0x1e ]) # at 

375 self.hc[0x41] = bytes([ 0x7e, 0x11, 0x11, 0x11, 0x7e ]) # UC A 

376 self.hc[0x42] = bytes([ 0x7f, 0x49, 0x49, 0x49, 0x36 ]) # UC B 

377 self.hc[0x43] = bytes([ 0x3e, 0x41, 0x41, 0x41, 0x22 ]) # UC C 

378 self.hc[0x44] = bytes([ 0x41, 0x7f, 0x41, 0x41, 0x3e ]) # UC D 

379 self.hc[0x45] = bytes([ 0x7f, 0x49, 0x49, 0x49, 0x41 ]) # UC E 

380 self.hc[0x46] = bytes([ 0x7f, 0x09, 0x09, 0x09, 0x01 ]) # UC F 

381 self.hc[0x47] = bytes([ 0x3e, 0x41, 0x41, 0x51, 0x72 ]) # UC G 

382 self.hc[0x48] = bytes([ 0x7f, 0x08, 0x08, 0x08, 0x7f ]) # UC H 

383 self.hc[0x49] = bytes([ 0x00, 0x41, 0x7f, 0x41, 0x00 ]) # UC I 

384 self.hc[0x4a] = bytes([ 0x20, 0x40, 0x40, 0x40, 0x3f ]) # UC J 

385 self.hc[0x4b] = bytes([ 0x7f, 0x08, 0x14, 0x22, 0x41 ]) # UC K 

386 self.hc[0x4c] = bytes([ 0x7f, 0x40, 0x40, 0x40, 0x40 ]) # UC L 

387 self.hc[0x4d] = bytes([ 0x7f, 0x02, 0x0c, 0x02, 0x7f ]) # UC M 

388 self.hc[0x4e] = bytes([ 0x7f, 0x04, 0x08, 0x10, 0x7f ]) # UC N 

389 self.hc[0x4f] = bytes([ 0x3e, 0x41, 0x41, 0x41, 0x3e ]) # UC O 

390 self.hc[0x50] = bytes([ 0x7f, 0x09, 0x09, 0x09, 0x06 ]) # UC P 

391 self.hc[0x51] = bytes([ 0x3e, 0x41, 0x51, 0x21, 0x5e ]) # UC Q 

392 self.hc[0x52] = bytes([ 0x7f, 0x09, 0x19, 0x29, 0x46 ]) # UC R 

393 self.hc[0x53] = bytes([ 0x26, 0x49, 0x49, 0x49, 0x32 ]) # UC S 

394 self.hc[0x54] = bytes([ 0x01, 0x01, 0x7f, 0x01, 0x01 ]) # UC T 

395 self.hc[0x55] = bytes([ 0x3f, 0x40, 0x40, 0x40, 0x3f ]) # UC U 

396 self.hc[0x56] = bytes([ 0x07, 0x18, 0x60, 0x18, 0x07 ]) # UC V 

397 self.hc[0x57] = bytes([ 0x7f, 0x20, 0x18, 0x20, 0x7f ]) # UC W 

398 self.hc[0x58] = bytes([ 0x63, 0x14, 0x08, 0x14, 0x63 ]) # UC X 

399 self.hc[0x59] = bytes([ 0x03, 0x04, 0x78, 0x04, 0x03 ]) # UC Y 

400 self.hc[0x5a] = bytes([ 0x61, 0x51, 0x49, 0x45, 0x43 ]) # UC Z 

401 self.hc[0x5b] = bytes([ 0x00, 0x7f, 0x41, 0x41, 0x00 ]) # left bracket 

402 self.hc[0x5c] = bytes([ 0x02, 0x04, 0x08, 0x10, 0x20 ]) # backslash 

403 self.hc[0x5d] = bytes([ 0x00, 0x41, 0x41, 0x7f, 0x00 ]) # right bracket 

404 self.hc[0x5e] = bytes([ 0x04, 0x02, 0x7f, 0x02, 0x04 ]) # up arrow 

405 self.hc[0x5f] = bytes([ 0x40, 0x40, 0x40, 0x40, 0x40 ]) # underscore 

406 self.hc[0x60] = bytes([ 0x00, 0x01, 0x07, 0x01, 0x00 ]) # superscript T 

407 self.hc[0x61] = bytes([ 0x20, 0x54, 0x54, 0x54, 0x78 ]) # LC a 

408 self.hc[0x62] = bytes([ 0x7f, 0x48, 0x44, 0x44, 0x38 ]) # LC b 

409 self.hc[0x63] = bytes([ 0x38, 0x44, 0x44, 0x44, 0x20 ]) # LC c 

410 self.hc[0x64] = bytes([ 0x38, 0x44, 0x44, 0x48, 0x7f ]) # LC d 

411 self.hc[0x65] = bytes([ 0x38, 0x54, 0x54, 0x54, 0x08 ]) # LC e 

412 self.hc[0x66] = bytes([ 0x08, 0x7c, 0x0a, 0x01, 0x02 ]) # LC f 

413 self.hc[0x67] = bytes([ 0x08, 0x14, 0x54, 0x54, 0x38 ]) # LC g 

414 self.hc[0x68] = bytes([ 0x7f, 0x10, 0x08, 0x08, 0x70 ]) # LC h 

415 self.hc[0x69] = bytes([ 0x00, 0x44, 0x7d, 0x40, 0x00 ]) # LC i 

416 self.hc[0x6a] = bytes([ 0x20, 0x40, 0x40, 0x3d, 0x00 ]) # LC j 

417 self.hc[0x6b] = bytes([ 0x00, 0x7f, 0x28, 0x44, 0x00 ]) # LC k 

418 self.hc[0x6c] = bytes([ 0x00, 0x41, 0x7f, 0x40, 0x00 ]) # LC l 

419 self.hc[0x6d] = bytes([ 0x78, 0x04, 0x18, 0x04, 0x78 ]) # LC m 

420 self.hc[0x6e] = bytes([ 0x7c, 0x08, 0x04, 0x04, 0x78 ]) # LC n 

421 self.hc[0x6f] = bytes([ 0x38, 0x44, 0x44, 0x44, 0x38 ]) # LC o 

422 self.hc[0x70] = bytes([ 0x7c, 0x14, 0x24, 0x24, 0x18 ]) # LC p 

423 self.hc[0x71] = bytes([ 0x18, 0x24, 0x24, 0x7c, 0x40 ]) # LC q 

424 self.hc[0x72] = bytes([ 0x7c, 0x08, 0x04, 0x04, 0x08 ]) # LC r 

425 self.hc[0x73] = bytes([ 0x48, 0x54, 0x54, 0x54, 0x24 ]) # LC s 

426 self.hc[0x74] = bytes([ 0x04, 0x3e, 0x44, 0x20, 0x00 ]) # LC t 

427 self.hc[0x75] = bytes([ 0x3c, 0x40, 0x40, 0x20, 0x7c ]) # LC u 

428 self.hc[0x76] = bytes([ 0x1c, 0x20, 0x40, 0x20, 0x1c ]) # LC v 

429 self.hc[0x77] = bytes([ 0x3c, 0x40, 0x30, 0x40, 0x3c ]) # LC w 

430 self.hc[0x78] = bytes([ 0x44, 0x28, 0x10, 0x28, 0x44 ]) # LC x 

431 self.hc[0x79] = bytes([ 0x44, 0x28, 0x10, 0x08, 0x04 ]) # LC y 

432 self.hc[0x7a] = bytes([ 0x44, 0x64, 0x54, 0x4c, 0x44 ]) # LC z 

433 self.hc[0x7b] = bytes([ 0x08, 0x78, 0x08, 0x78, 0x04 ]) # LC pi 

434 self.hc[0x7c] = bytes([ 0x60, 0x50, 0x58, 0x64, 0x42 ]) # angle 

435 self.hc[0x7d] = bytes([ 0x08, 0x08, 0x2a, 0x1c, 0x08 ]) # right arrow 

436 self.hc[0x7e] = bytes([ 0x63, 0x55, 0x49, 0x41, 0x63 ]) # UC sigma 

437 self.hc[0x7f] = bytes([ 0x7f, 0x08, 0x08, 0x08, 0x08 ]) # lazy T 

438 self.charset= CHARSET_ASCII 

439 

440 def set_charset(self,c): 

441 self.charset=c 

442 

443 def get(self,c,i): 

444 if self.charset== CHARSET_ASCII: 

445 return self.ac[c][i] 

446 else: 

447 return self.hc[c][i] 

448# 

449# HP82162A tab widget --------------------------------------------------------- 

450# 

451class cls_tabhp82162a(cls_tabgeneric): 

452 

453 

454 def __init__(self,parent,name): 

455 super().__init__(parent,name) 

456 self.name=name 

457# 

458# this parameter is global 

459# 

460 self.papersize=PILCONFIG.get("pyilper","papersize") 

461# 

462# init local parameter 

463# 

464 self.pixelsize=PILCONFIG.get(self.name,"hp82162a_pixelsize",-1) 

465# 

466# create Printer GUI object 

467# 

468 self.guiobject=cls_HP82162AWidget(self,self.name,self.papersize) 

469# 

470# add gui object  

471# 

472 self.add_guiobject(self.guiobject) 

473# 

474# add cascading config menu 

475# 

476 self.add_configwidget() 

477# 

478# add local config option 

479# 

480 self.cBut.add_option("Pixel size","hp82162a_pixelsize",T_INTEGER,[O_DEFAULT,1,2]) 

481# 

482# add logging control widget 

483# 

484 self.add_logging() 

485# 

486# create IL-Interface object, notify printer processor object 

487# 

488 self.pildevice= cls_pilhp82162a(self.guiobject) 

489 self.guiobject.set_pildevice(self.pildevice) 

490 self.cBut.config_changed_signal.connect(self.do_tabconfig_changed) 

491# 

492# handle changes of tab config options 

493# 

494 def do_tabconfig_changed(self): 

495 self.loglevel= PILCONFIG.get(self.name,"loglevel",0) 

496 self.guiobject.reconfigure() 

497 super().do_tabconfig_changed() 

498# 

499# reconfigure: reconfigure the gui object 

500# 

501 def reconfigure(self): 

502 self.guiobject.reconfigure() 

503# 

504# enable pildevice and gui object 

505# 

506 def enable(self): 

507 super().enable() 

508 self.parent.commthread.register(self.pildevice,self.name) 

509 self.pildevice.setactive(self.active) 

510 self.pildevice.enable() 

511 self.guiobject.enable() 

512# 

513# disable pildevice and gui object 

514# 

515 def disable(self): 

516 self.pildevice.disable() 

517 self.guiobject.disable() 

518 super().disable() 

519# 

520# active/inactive: enable/disable GUI controls 

521# 

522 def toggle_active(self): 

523 super().toggle_active() 

524 self.guiobject.toggle_active() 

525# 

526# becomes visible, refresh content, activate update 

527# 

528 def becomes_visible(self): 

529 self.guiobject.becomes_visible() 

530 return 

531# 

532# becomes invisible, deactivate update 

533# 

534 def becomes_invisible(self): 

535 self.guiobject.becomes_invisible() 

536 return 

537# 

538# 

539# HP82162A widget classes - GUI component of the HP82162A HP-IL printer 

540# 

541class cls_HP82162AWidget(QtWidgets.QWidget): 

542 

543 def __init__(self,parent,name,papersize): 

544 super().__init__() 

545 self.name= name 

546 self.parent= parent 

547 self.papersize= papersize 

548 self.pildevice= None 

549# 

550# configuration 

551# 

552 self.pdfpixelsize=3 

553 self.pixelsize=PILCONFIG.get_dual(self.name,"hp82162a_pixelsize") 

554 self.linebuffersize=HP82162A_LINEBUFFERSIZE 

555 self.printer_modeswitch= PILCONFIG.get(self.name,"modeswitch",MODESWITCH_MAN) 

556# 

557# create user interface of printer widget 

558# 

559 self.hbox=QtWidgets.QHBoxLayout() 

560 self.hbox.addStretch(1) 

561# 

562# scrolled printer view 

563# 

564 self.printview=cls_ScrolledHP82162AView(self,self.name,self.pixelsize, self.pdfpixelsize,self.papersize,self.linebuffersize) 

565 self.hbox.addWidget(self.printview) 

566 self.vbox=QtWidgets.QVBoxLayout() 

567# 

568# radio buttons Man, Norm, Trace 

569# 

570 self.gbox= QtWidgets.QGroupBox() 

571 self.gbox.setFlat(True) 

572 self.gbox.setTitle("Printer mode") 

573 self.vboxgbox= QtWidgets.QVBoxLayout() 

574 self.gbox.setLayout(self.vboxgbox) 

575# 

576# Man Mode 

577# 

578 self.radbutMan= QtWidgets.QRadioButton(self.gbox) 

579 self.radbutMan.setEnabled(False) 

580 self.radbutMan.setText("Man") 

581 self.radbutMan.toggled.connect(self.toggledCheckBoxes) 

582 self.vboxgbox.addWidget(self.radbutMan) 

583# 

584# Trace Mode 

585# 

586 self.radbutTrace= QtWidgets.QRadioButton(self.gbox) 

587 self.radbutTrace.setEnabled(False) 

588 self.radbutTrace.setText("Trace") 

589 self.radbutTrace.toggled.connect(self.toggledCheckBoxes) 

590 self.vboxgbox.addWidget(self.radbutTrace) 

591# 

592# Norm Mode 

593# 

594 self.radbutNorm= QtWidgets.QRadioButton(self.gbox) 

595 self.radbutNorm.setEnabled(False) 

596 self.radbutNorm.setText("Norm") 

597 self.radbutNorm.toggled.connect(self.toggledCheckBoxes) 

598 self.vboxgbox.addWidget(self.radbutNorm) 

599 

600 self.vbox.addWidget(self.gbox) 

601# 

602# Clear Button 

603# 

604 self.clearButton= QtWidgets.QPushButton("Clear") 

605 self.clearButton.setEnabled(False) 

606 self.clearButton.setAutoDefault(False) 

607 self.vbox.addWidget(self.clearButton) 

608 self.clearButton.clicked.connect(self.do_clear) 

609# 

610# Print Button 

611# 

612 self.printButton= QtWidgets.QPushButton("Print") 

613 self.printButton.setEnabled(False) 

614 self.printButton.setAutoDefault(False) 

615 self.vbox.addWidget(self.printButton) 

616 self.printButton.pressed.connect(self.do_print_pressed) 

617 self.printButton.released.connect(self.do_print_released) 

618# 

619# Paper Advance Button 

620# 

621 self.advanceButton= QtWidgets.QPushButton("Advance") 

622 self.advanceButton.setEnabled(False) 

623 self.advanceButton.setAutoDefault(False) 

624 self.vbox.addWidget(self.advanceButton) 

625 self.advanceButton.pressed.connect(self.do_advance_pressed) 

626 self.advanceButton.released.connect(self.do_advance_released) 

627# 

628# PDF Button 

629# 

630 self.pdfButton= QtWidgets.QPushButton("PDF") 

631 self.pdfButton.setEnabled(False) 

632 self.pdfButton.setAutoDefault(False) 

633 self.vbox.addWidget(self.pdfButton) 

634 self.pdfButton.clicked.connect(self.do_pdf) 

635 

636 self.vbox.addStretch(1) 

637 self.hbox.addLayout(self.vbox) 

638 self.hbox.addStretch(1) 

639 self.setLayout(self.hbox) 

640# 

641# initialize GUI command queue and lock 

642# 

643 self.gui_queue= queue.Queue() 

644 self.gui_queue_lock= threading.Lock() 

645# 

646# initialize refresh timer 

647# 

648 self.UpdateTimer=QtCore.QTimer() 

649 self.UpdateTimer.setSingleShot(True) 

650 self.UpdateTimer.timeout.connect(self.process_queue) 

651# 

652# initialize timer for the repeated pressed advance button action 

653# 

654 self.repeatedAdvpressedTimer=QtCore.QTimer() 

655 self.repeatedAdvpressedTimer.timeout.connect(self.repeated_advpressed) 

656 self.repeatedAdvpressedTimer.setInterval(1500) 

657# 

658# set HP-IL device object 

659# 

660 def set_pildevice(self,pildevice): 

661 self.pildevice=pildevice 

662# 

663# enable: start timer, send mode to virtual device, update check boxes 

664# 

665 def enable(self): 

666 self.UpdateTimer.start(UPDATE_TIMER) 

667 self.setCheckBoxes() 

668 if self.printer_modeswitch== MODESWITCH_MAN: 

669 self.pildevice.put_cmd(CMD_MAN) 

670 if self.printer_modeswitch== MODESWITCH_TRACE: 

671 self.pildevice.put_cmd(CMD_TRACE) 

672 if self.printer_modeswitch== MODESWITCH_NORM: 

673 self.pildevice.put_cmd(CMD_NORM) 

674 self.toggle_active() 

675 return 

676# 

677# disable, clear the GUI queue, stop the timer 

678# 

679 def disable(self): 

680 self.gui_queue_lock.acquire() 

681 while True: 

682 try: 

683 self.gui_queue.get_nowait() 

684 self.gui_queue.task_done() 

685 except queue.Empty: 

686 break 

687 self.gui_queue_lock.release() 

688 self.UpdateTimer.stop() 

689 return 

690# 

691# becomes visible 

692# 

693 def becomes_visible(self): 

694 self.printview.becomes_visible() 

695# 

696# becomes invisible, do nothing 

697# 

698 def becomes_invisible(self): 

699 pass 

700# 

701# active/inactive: enable/disable GUI controls 

702# 

703 def toggle_active(self): 

704 if self.parent.active: 

705 self.radbutMan.setEnabled(True) 

706 self.radbutTrace.setEnabled(True) 

707 self.radbutNorm.setEnabled(True) 

708 self.clearButton.setEnabled(True) 

709 self.printButton.setEnabled(True) 

710 self.advanceButton.setEnabled(True) 

711 self.pdfButton.setEnabled(True) 

712 else: 

713 self.radbutMan.setEnabled(False) 

714 self.radbutTrace.setEnabled(False) 

715 self.radbutNorm.setEnabled(False) 

716 self.clearButton.setEnabled(False) 

717 self.printButton.setEnabled(False) 

718 self.advanceButton.setEnabled(False) 

719 self.pdfButton.setEnabled(False) 

720# 

721# reconfigure 

722# 

723 def reconfigure(self): 

724 self.printview.reconfigure() 

725 return 

726# 

727# action scripts 

728# 

729 def do_clear(self): 

730 self.printview.reset() 

731 self.pildevice.put_cmd(CMD_CLEAR) 

732 return 

733 

734 def do_print_pressed(self): 

735 self.pildevice.put_cmd(CMD_PRINT_PRESSED) 

736 return 

737 

738 def do_advance_pressed(self): 

739 self.pildevice.put_cmd(CMD_ADV_PRESSED) 

740 self.repeatedAdvpressedTimer.start() 

741 return 

742 

743 def do_print_released(self): 

744 self.pildevice.put_cmd(CMD_PRINT_RELEASED) 

745 return 

746 

747 def do_advance_released(self): 

748 self.pildevice.put_cmd(CMD_ADV_RELEASED) 

749 self.repeatedAdvpressedTimer.stop() 

750 return 

751 

752 def do_pdf(self): 

753 self.pdf_columns=PILCONFIG.get(self.name,"pdfcolumns",3) 

754 options=cls_PdfOptions.getPdfOptions(self.pdf_columns,"") 

755 if options== "": 

756 return 

757 PILCONFIG.put(self.name,"pdfcolumns",options[1]) 

758 self.printview.pdf(options[0],options[1],options[2]) 

759 return 

760# 

761# handle change of check boxes 

762# 

763 def toggledCheckBoxes(self): 

764 if self.radbutMan.isChecked(): 

765 self.pildevice.put_cmd(CMD_MAN) 

766 self.printer_modeswitch= MODESWITCH_MAN 

767 self.setCheckBoxes() 

768 if self.radbutTrace.isChecked(): 

769 self.pildevice.put_cmd(CMD_TRACE) 

770 self.printer_modeswitch= MODESWITCH_TRACE 

771 self.setCheckBoxes() 

772 if self.radbutNorm.isChecked(): 

773 self.pildevice.put_cmd(CMD_NORM) 

774 self.printer_modeswitch= MODESWITCH_NORM 

775 self.setCheckBoxes() 

776 PILCONFIG.put(self.name,"modeswitch",self.printer_modeswitch) 

777# 

778# set check box according to self.printer_modeswitch 

779# 

780 def setCheckBoxes(self): 

781 if self.printer_modeswitch== MODESWITCH_NORM: 

782 self.radbutNorm.setChecked(True) 

783 self.radbutMan.setChecked(False) 

784 self.radbutTrace.setChecked(False) 

785 if self.printer_modeswitch== MODESWITCH_MAN: 

786 self.radbutNorm.setChecked(False) 

787 self.radbutMan.setChecked(True) 

788 self.radbutTrace.setChecked(False) 

789 if self.printer_modeswitch== MODESWITCH_TRACE: 

790 self.radbutNorm.setChecked(False) 

791 self.radbutMan.setChecked(False) 

792 self.radbutTrace.setChecked(True) 

793 return 

794# 

795# put command into the GUI-command queue, this is called by the thread component 

796# 

797 def put_cmd(self,item): 

798 self.gui_queue_lock.acquire() 

799 self.gui_queue.put(item) 

800 self.gui_queue_lock.release() 

801# 

802# repeated adv pressed action 

803# 

804 def repeated_advpressed(self): 

805 b=bytes(0) 

806 self.put_cmd([REMOTECMD_PRINT,b,1]) 

807# 

808# process commands in the GUI command queue, this is called by a timer event 

809# 

810 def process_queue(self): 

811 items=[] 

812 self.gui_queue_lock.acquire() 

813 while True: 

814 try: 

815 i=self.gui_queue.get_nowait() 

816 items.append(i) 

817 self.gui_queue.task_done() 

818 except queue.Empty: 

819 break 

820 self.gui_queue_lock.release() 

821 if len(items): 

822 for c in items: 

823 self.process(c) 

824 self.UpdateTimer.start(UPDATE_TIMER) 

825 return 

826# 

827# GUI command processing, commands issued by the HP-IL thread 

828# 

829 def process(self,item): 

830 cmd= item[0] 

831# 

832# clear graphhics views  

833# 

834 if cmd== REMOTECMD_CLEAR: 

835 self.printview.reset() 

836# 

837# output line 

838# 

839 elif cmd== REMOTECMD_PRINT: 

840 line= item[1] 

841 col_idx= item[2] 

842 self.printview.add_line(line,col_idx) 

843# 

844# log line 

845# 

846 elif cmd== REMOTECMD_LOG: 

847 self.parent.cbLogging.logWrite(item[1]) 

848 self.parent.cbLogging.logFlush() 

849# 

850# custom class for scrolled hp82162a output widget ---------------------------- 

851# 

852class cls_ScrolledHP82162AView(QtWidgets.QWidget): 

853 

854 def __init__(self,parent,name,pixelsize,pdfpixelsize,papersize,linebuffersize): 

855 super().__init__(parent) 

856 self.parent=parent 

857 self.name=name 

858#  

859# create window and scrollbars 

860# 

861 

862 self.hbox= QtWidgets.QHBoxLayout() 

863 self.scrollbar= QtWidgets.QScrollBar() 

864 self.hp82162awidget= cls_HP82162aView(self,self.name,pixelsize,pdfpixelsize,papersize,linebuffersize) 

865 self.hp82162awidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 

866 self.hp82162awidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) 

867 self.hbox.addWidget(self.hp82162awidget) 

868 self.hbox.addWidget(self.scrollbar) 

869 self.setLayout(self.hbox) 

870# 

871# Initialize scrollbar 

872# 

873 self.scrollbar.valueChanged.connect(self.do_scrollbar) 

874 self.scrollbar.setEnabled(True) 

875 self.reset() 

876# 

877# scrollbar value changed action 

878# 

879 def do_scrollbar(self): 

880 self.hp82162awidget.do_scroll(self.scrollbar.value()) 

881# 

882# add line to printer output window 

883# 

884 def add_line(self,line,col_idx): 

885 self.hp82162awidget.add_line(line,col_idx) 

886# 

887# reset output window 

888# 

889 def reset(self): 

890 self.hp82162awidget.reset() 

891 self.scrollbar.setMinimum(0) 

892 self.scrollbar.setMaximum(0) 

893 self.scrollbar.setSingleStep(1) 

894# 

895# generate pdf output 

896# 

897 def pdf(self,filename,columns,title): 

898 self.hp82162awidget.pdf(filename,columns,title) 

899# 

900# becomes visible/invisible: nothing to do 

901# 

902 def becomes_visible(self): 

903 return 

904 

905 def becomes_invisible(self): 

906 return 

907# 

908# reconfigure 

909# 

910 def reconfigure(self): 

911 self.hp82162awidget.reconfigure() 

912 return 

913 

914# 

915# custom class for hp82162a output ----------------------------------------- 

916# 

917class cls_HP82162aView(QtWidgets.QGraphicsView): 

918 

919 def __init__(self,parent,name,pixelsize,pdfpixelsize,papersize,linebuffersize): 

920 super().__init__() 

921 self.parent=parent 

922 self.name= name 

923# 

924# initial output window in reconfigure 

925# 

926 self.pixelsize= -1 

927 self.w=-1 

928 self.h=-1 

929 self.pdfpixelsize= pdfpixelsize 

930 self.pdfw=PRINTER_WIDTH_CHARS*PRINTER_CHARACTER_WIDTH_PIXELS*pdfpixelsize 

931 self.pdfh=PRINTER_CHARACTER_HEIGHT_PIXELS*pdfpixelsize 

932 self.rows= 0 

933 self.linebuffersize= linebuffersize 

934 self.papersize= papersize 

935# 

936# initialize line bitmap buffer 

937# 

938 self.lb= [None] * linebuffersize 

939 self.lb_current= -1 

940 self.lb_anz=0 

941 self.lb_position=0 

942 

943 self.printscene=None 

944 self.pdfprinter=None 

945 self.reconfigure() 

946# 

947# configure/reconfigure the printview widget, scene and its content 

948# 

949 def reconfigure(self): 

950 tmp=PILCONFIG.get_dual(self.name,"hp82162a_pixelsize") 

951# 

952# re/configure the printview widget 

953# 

954 if tmp != self.pixelsize: 

955 self.pixelsize=tmp 

956 self.w=PRINTER_WIDTH_CHARS*PRINTER_CHARACTER_WIDTH_PIXELS*self.pixelsize 

957 self.h=PRINTER_CHARACTER_HEIGHT_PIXELS*self.pixelsize 

958# 

959# set fixed width 

960# 

961 self.setFixedWidth(self.w+2*self.pixelsize) 

962# 

963# initialize scene if not existing 

964# 

965 if self.printscene is None: 

966 self.printscene= cls_hp82162a_scene(self,self.pixelsize) 

967 self.setScene(self.printscene) 

968 self.reset() 

969# 

970# otherwise reconfigure scene and its content 

971# 

972 else: 

973 self.printscene.reconfigure(self.pixelsize) 

974 for i in range(0,self.linebuffersize): 

975 if self.lb[i] is not None: 

976 self.lb[i].reconfigure(self.pixelsize) 

977 self.do_resize() 

978# 

979# now shrink all parent windows to minimum size 

980# 

981# w=self.parentWidget() 

982# while w is not None: 

983# w.adjustSize() 

984# w=w.parentWidget() 

985 return 

986# 

987# reset output window 

988# 

989 def reset(self): 

990 for i in range(0,self.linebuffersize): 

991 if self.lb[i] is not None: 

992 self.lb[i]= None 

993 self.lb_current= -1 

994 self.lb_anz=0 

995 self.lb_position=0 

996 self.printscene.reset() 

997# 

998# overwrite standard events 

999# 

1000# resize event, adjust the scene size, reposition everything and redraw 

1001# 

1002 def resizeEvent(self,event): 

1003 self.do_resize() 

1004 

1005 def do_resize(self): 

1006 h=self.height() 

1007 self.rows=h // (PRINTER_CHARACTER_HEIGHT_PIXELS*self.pixelsize) 

1008 self.printscene.set_scenesize(self.rows) 

1009 scroll_max=self.lb_current- self.rows+1 

1010 if scroll_max < 0: 

1011 scroll_max=0 

1012 self.parent.scrollbar.setMaximum(scroll_max) 

1013 self.parent.scrollbar.setPageStep(self.rows) 

1014 self.printscene.update_scene() 

1015 return 

1016# 

1017# Mouse wheel event 

1018# 

1019 def wheelEvent(self,event): 

1020 numDegrees= event.angleDelta()/8 

1021 delta=0 

1022 if numDegrees.y() is not None: 

1023 if numDegrees.y() < 0: 

1024 delta=1 

1025 if numDegrees.y() > 0: 

1026 delta=-1 

1027 event.accept() 

1028 if self.lb_current < self.rows: 

1029 return 

1030 if self.lb_position+delta <0 or self.lb_position+delta+self.rows-1 > self.lb_current: 

1031 return 

1032 self.lb_position+=delta 

1033 self.parent.scrollbar.setValue(self.lb_position) 

1034 self.printscene.update_scene() 

1035 return 

1036# 

1037# external methods 

1038# 

1039 def add_line(self,line,col_idx): 

1040# 

1041# add line bitmap to line bitmap buffer 

1042# 

1043 if self.lb_anz < self.linebuffersize: 

1044 self.lb_anz+=1 

1045 self.lb_current+=1 

1046 self.lb[self.lb_current]=cls_hp82162a_line(line,col_idx,self.pixelsize,) 

1047 else: 

1048 self.lb= self.lb[1:] + self.lb[:1] 

1049 self.lb[self.lb_current]=cls_hp82162a_line(line,col_idx,self.pixelsize,) 

1050 self.lb_position=self.lb_current- self.rows+1 

1051 if self.lb_position < 0: 

1052 self.lb_position=0 

1053 self.parent.scrollbar.setMaximum(self.lb_position) 

1054 self.parent.scrollbar.setValue(self.lb_position) 

1055 

1056 self.printscene.update_scene() 

1057# 

1058# scroll bar action 

1059# 

1060 def do_scroll(self,value): 

1061 self.lb_position=value 

1062 self.printscene.update_scene() 

1063# 

1064# PDF output of lb buffer content, prints with page number and optional 

1065# header. Output is formatted in 1-3 columns 

1066# 

1067 def pdf(self,filename,columns,title): 

1068 

1069 self.pdfprinter= cls_pdfprinter(self.papersize,PDF_ORIENTATION_PORTRAIT,filename, title, True, columns) 

1070 self.pdfprinter.begin() 

1071#  

1072# process lines 

1073# 

1074 k=0 

1075 while True: 

1076# 

1077# end of output 

1078# 

1079 if k == self.lb_anz: 

1080 break 

1081 item_args= cls_hp82162a_line.from_hp82162a_line(self.lb[k]) 

1082 item= cls_hp82162a_line(item_args[0],item_args[1],self.pdfpixelsize) 

1083 self.pdfprinter.print_item(item) 

1084 k+=1 

1085 self.pdfprinter.end() 

1086 

1087# 

1088# custom class for line bitmap ---------------------------------------------- 

1089# 

1090class cls_hp82162a_line(QtWidgets.QGraphicsItem): 

1091 

1092 def __init__(self,line, col_idx, pixelsize): 

1093 super().__init__() 

1094 self.pixelsize=-1 

1095 self.w=-1 

1096 self.h=-1 

1097 self.rect= QtCore.QRectF(0,0,1,1) 

1098 self.col_idx=col_idx 

1099 self.line=bytes(line[:col_idx]) 

1100 self.reconfigure(pixelsize) 

1101 

1102 def reconfigure(self,pixelsize): 

1103 self.pixelsize=pixelsize 

1104 self.w=PRINTER_WIDTH_CHARS*PRINTER_CHARACTER_WIDTH_PIXELS*pixelsize 

1105 self.h=PRINTER_CHARACTER_HEIGHT_PIXELS*pixelsize 

1106 self.rect= QtCore.QRectF(0,0,self.w,self.h) 

1107 

1108 def setPos(self,x,y): 

1109 super().setPos(x,y-self.h) 

1110 

1111 

1112 def boundingRect(self): 

1113 return self.rect 

1114# 

1115# paint bitmap 

1116# 

1117 def paint(self,painter,option,widget): 

1118 

1119 posx=0 

1120 for b in self.line: 

1121 posy=0 

1122 for i in range(0,8): 

1123 if b & 0x01: 

1124 painter.fillRect(posx,posy,self.pixelsize,self.pixelsize,QtCore.Qt.black) 

1125 b= b>>1 

1126 posy+= self.pixelsize 

1127 posx+= self.pixelsize 

1128# 

1129# get a copy of the constructor parameters 

1130# 

1131 @classmethod 

1132 def from_hp82162a_line(cls, class_instance): 

1133 line= copy.deepcopy(class_instance.line) 

1134 return(line,class_instance.col_idx) 

1135 

1136# 

1137# custom class for hp82162a graphics scene 

1138# 

1139class cls_hp82162a_scene(QtWidgets.QGraphicsScene): 

1140 

1141 def __init__(self,parent,pixelsize): 

1142 super().__init__() 

1143 self.rows= 0 

1144 self.w=0 

1145 self.h=0 

1146 self.parent=parent 

1147 self.si= None 

1148 self.reconfigure(pixelsize) 

1149 return 

1150# 

1151# re/configure graphics scene 

1152# 

1153 def reconfigure(self,pixelsize): 

1154 self.pixelsize=pixelsize 

1155 self.w=PRINTER_WIDTH_CHARS*PRINTER_CHARACTER_WIDTH_PIXELS*pixelsize 

1156 self.h=PRINTER_CHARACTER_HEIGHT_PIXELS*pixelsize 

1157 return 

1158# 

1159# set or change the size of the scene 

1160# 

1161 def set_scenesize(self,rows): 

1162 self.reset() 

1163 self.rows= rows 

1164 self.si= [None] * rows 

1165 self.setSceneRect(0,0,self.w,self.h*self.rows) 

1166# 

1167# clear window and reset 

1168# 

1169 def reset(self): 

1170 for i in range(0,self.rows): 

1171 if self.si[i] is not None: 

1172 self.removeItem(self.si[i]) 

1173 self.si[i]=None 

1174# 

1175# update graphics scene 

1176# 

1177 def update_scene(self): 

1178 for i in range(0,self.rows): 

1179 if self.si[i] is not None: 

1180 self.removeItem(self.si[i]) 

1181 self.si[i]=None 

1182 start= self.parent.lb_position 

1183 end= start+self.rows 

1184 

1185 if end >= self.parent.lb_anz: 

1186 end=self.parent.lb_anz 

1187 y=self.h 

1188 j=0 

1189 for i in range(start,end): 

1190 self.si[j]=self.parent.lb[i] 

1191 self.addItem(self.si[j]) 

1192 self.si[j].setPos(0,y) 

1193 y+=self.h+DISPLAY_LINE_SPACING*self.pixelsize 

1194 j+=1 

1195# 

1196# custom class open pdf output file and set options 

1197# 

1198 

1199class cls_PdfOptions(QtWidgets.QDialog): 

1200 

1201 def __init__(self,columns,title): 

1202 super().__init__() 

1203 self.columns=columns 

1204 self.title=title 

1205 self.filename="hp82162a.pdf" 

1206 self.setWindowTitle('HP82162A PDF output') 

1207 self.vlayout = QtWidgets.QVBoxLayout() 

1208 self.setLayout(self.vlayout) 

1209 self.glayout = QtWidgets.QGridLayout() 

1210 self.vlayout.addLayout(self.glayout) 

1211 

1212 self.glayout.addWidget(QtWidgets.QLabel("PDF Output Options"),0,0,1,3) 

1213 self.glayout.addWidget(QtWidgets.QLabel("Output file:"),1,0) 

1214 self.filename="hp82162a.pdf" 

1215 self.lfilename=QtWidgets.QLabel(self.filename) 

1216 self.glayout.addWidget(self.lfilename,1,1) 

1217 self.butchange=QtWidgets.QPushButton("Change") 

1218 self.butchange.setFixedWidth(60) 

1219 self.glayout.addWidget(self.butchange,1,2) 

1220 self.glayout.addWidget(QtWidgets.QLabel("Title:"),2,0) 

1221 self.edttitle=QtWidgets.QLineEdit() 

1222 self.edttitle.setText(self.title) 

1223 self.edttitle.setFixedWidth(200) 

1224 self.glayout.addWidget(self.edttitle,2,1,1,2) 

1225 self.glayout.addWidget(QtWidgets.QLabel("Columns:"),3,0) 

1226 self.spincolumns=QtWidgets.QSpinBox() 

1227 self.spincolumns.setMinimum(1) 

1228 self.spincolumns.setMaximum(PDF_MAX_COLS) 

1229 self.spincolumns.setValue(self.columns) 

1230 self.glayout.addWidget(self.spincolumns,3,1,1,2) 

1231 

1232 self.buttonBox = QtWidgets.QDialogButtonBox() 

1233 self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) 

1234 self.buttonBox.setCenterButtons(True) 

1235 self.buttonBox.accepted.connect(self.do_ok) 

1236 self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) 

1237 self.buttonBox.rejected.connect(self.do_cancel) 

1238 self.hlayout = QtWidgets.QHBoxLayout() 

1239 self.hlayout.addWidget(self.buttonBox) 

1240 self.vlayout.addLayout(self.hlayout) 

1241 self.butchange.clicked.connect(self.change_pdffile) 

1242 

1243 def get_pdfFilename(self): 

1244 dialog=QtWidgets.QFileDialog() 

1245 dialog.setWindowTitle("Enter PDF file name") 

1246 dialog.setAcceptMode(QtWidgets.QFileDialog.AcceptSave) 

1247 dialog.setFileMode(QtWidgets.QFileDialog.AnyFile) 

1248 dialog.setDefaultSuffix("pdf") 

1249 dialog.setNameFilters( ["PDF (*.pdf )", "All Files (*)"] ) 

1250 dialog.setOptions(QtWidgets.QFileDialog.DontUseNativeDialog) 

1251 if dialog.exec(): 

1252 return dialog.selectedFiles() 

1253 

1254 def change_pdffile(self): 

1255 flist= self.get_pdfFilename() 

1256 if flist is None: 

1257 return 

1258 self.filename= flist [0] 

1259 self.lfilename.setText(self.filename) 

1260 self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True) 

1261 

1262 

1263 def do_ok(self): 

1264 super().accept() 

1265 

1266 def do_cancel(self): 

1267 super().reject() 

1268 

1269 @staticmethod 

1270 def getPdfOptions(columns,title): 

1271 dialog= cls_PdfOptions(columns,title) 

1272 result= dialog.exec() 

1273 if result== QtWidgets.QDialog.Accepted: 

1274 return dialog.lfilename.text(), dialog.spincolumns.value(), dialog.edttitle.text() 

1275 else: 

1276 return "" 

1277# 

1278# Printer buffer object each entry has the following information: 

1279# value: value of entry 

1280# types: character, column data, barcode data 

1281# mode: current printer mode (we need double wide and lowercase mode) 

1282# width: pixel width of information 

1283# 

1284class cls_printer_buffer(object): 

1285 

1286 def __init__(self): 

1287 self.buffer= [] 

1288 self.buffer_pxlen=0 # total length of buffer entries in pixel 

1289 self.buffer_fmtpos=-1 # position of first fmt specifier 

1290 

1291 def add(self,v,t,m): 

1292 s=0 

1293 if t== type_column: 

1294 if m & mode_doublewide: 

1295 s=2 

1296 else: 

1297 s=1 

1298 if t== type_char: 

1299 if m & mode_doublewide: 

1300 s=14 

1301 else: 

1302 s=7 

1303 if t== type_skip: 

1304 if v >= 0xa0 and v <= 0xb7: 

1305 n= v - 0xa0 

1306 if m & mode_doublewide: 

1307 s= 14 * n 

1308 else: 

1309 s= 7 * n 

1310 if v >= 0xb8 and v <= 0xbf: 

1311 n= v- 0xb8 

1312 if m & mode_doublewide: 

1313 s= 2 * n 

1314 else: 

1315 s= n 

1316 if t== type_format and self.buffer_fmtpos<0: 

1317 self.buffer_fmtpos=len(self.buffer) 

1318 self.buffer.append([v,t,m,s]) 

1319 self.buffer_pxlen+=s 

1320 return 

1321 

1322 def get(self,idx): 

1323 if idx >= len(self.buffer): 

1324 return None 

1325 return self.buffer[idx] 

1326 

1327 def clear(self): 

1328 self.buffer_pxlen=0 

1329 self.buffer_fmtpos= -1 

1330 del self.buffer[:] 

1331 

1332 def length(self): 

1333 return len(self.buffer) 

1334 

1335 def pxlen(self): 

1336 return (self.buffer_pxlen) 

1337 

1338 def fmtpos(self): 

1339 return(self.buffer_fmtpos) 

1340# 

1341# line buffer object ------------------------------------------------------- 

1342# 

1343class cls_line_buffer(object): 

1344 

1345 def __init__(self,guiobject): 

1346 self.guiobject= guiobject # reference to GUI object  

1347 self.linebuffer= bytearray(PRINTER_WIDTH) # the line buffer 

1348 self.linebuffer_index=0 # current index in line buffer 

1349 self.wrap_position=-1 # pointer to wrap line position 

1350# 

1351# clear line buffer 

1352# 

1353 def clear(self): 

1354 self.linebuffer_index=0 

1355 self.wrap_position= -1 

1356# 

1357# print whole content of line buffer (end of line condition) 

1358# 

1359 def prt(self): 

1360 linebuffer_copy=copy.deepcopy(self.linebuffer) 

1361 self.guiobject.put_cmd([REMOTECMD_PRINT,linebuffer_copy,self.linebuffer_index]) 

1362 self.linebuffer_index=0 

1363 self.wrap_position= -1 

1364# 

1365# add column to line buffer, if we have an overflow then print it. If we are in 

1366# parse mode then break line at self.wrap_position 

1367# 

1368 def add(self,c,mode,wrap): 

1369 if wrap: 

1370 self.wrap_position=self.linebuffer_index 

1371 if self.linebuffer_index== PRINTER_WIDTH: 

1372 if mode & mode_parse and self.wrap_position>0: 

1373 linebuffer_copy=copy.deepcopy(self.linebuffer[:self.wrap_position-1]) 

1374 self.guiobject.put_cmd([REMOTECMD_PRINT,linebuffer_copy,self.wrap_position-1]) 

1375# next data 

1376 do_copy=False 

1377 j=1 

1378 self.linebuffer[0]=0 

1379 for i in range (PRINTER_WIDTH- self.wrap_position): 

1380 k=i+self.wrap_position 

1381 if self.linebuffer[k]!= 0 and not do_copy: 

1382 do_copy= True 

1383 if do_copy: 

1384 self.linebuffer[j]= self.linebuffer[k] 

1385 self.linebuffer[k]= 0 

1386 j+=1 

1387 

1388 self.linebuffer_index= j 

1389 self.wrap_positon= -1 

1390 else: 

1391 linebuffer_copy=copy.deepcopy(self.linebuffer) 

1392 self.guiobject.put_cmd([REMOTECMD_PRINT,linebuffer_copy,self.linebuffer_index]) 

1393 self.linebuffer_index=0 

1394 self.wrap_position= -1 

1395 

1396 self.linebuffer[self.linebuffer_index]=c 

1397 self.linebuffer_index+=1 

1398# 

1399# HP82162A emulator (thread component) -------------------------------------- 

1400# 

1401 

1402class cls_special_k(QtCore.QObject): 

1403 

1404 def __init__(self,parent,guiobject): 

1405 super().__init__() 

1406 self.pildevice=parent 

1407 self.guiobject= guiobject 

1408 self.printer_buffer= cls_printer_buffer() # printer buffer 

1409 self.line_buffer= cls_line_buffer(self.guiobject) # line buffer 

1410 self.char_gen= hp82162a_char() # character generator 

1411 self.esc= False # escape mode 

1412 self.esc_seq="" # escape sequence 

1413 self.esc_prefix="" # prefix of combined esc sequence 

1414 self.printer_mode=0 # printer mode bits 

1415 self.num_barcode=0 # number of barcodes to read 

1416 self.num_graphics=0 # number of graphics codes to read 

1417 self.bclist= { } 

1418 self.bcline= { } 

1419# 

1420# device clear, carriage positioned to right, print buffer cleared modes set 

1421# to Escape, Single Wide, Left-Justify and Nonparse 

1422# 

1423 def reset(self): 

1424 self.printer_buffer.clear() 

1425 self.line_buffer.clear() 

1426 self.esc= False 

1427 self.esc_seq="" 

1428 self.esc_prefix="" 

1429 self.printer_mode=0 

1430 self.char_gen.set_charset(CHARSET_ASCII) 

1431 self.num_barcode=0 

1432 self.num_graphics=0 

1433# 

1434# issue clear to GUI 

1435# 

1436 self.guiobject.put_cmd([REMOTECMD_CLEAR]) 

1437# 

1438# we are idle and buffer is empty 

1439# 

1440 self.set_status(STA_BE) 

1441 self.set_status(STA_ID) 

1442# 

1443# set, clear, query printer mode 

1444# 

1445 def setMode(self,mode_bit): 

1446 self.printer_mode= self.printer_mode | mode_bit 

1447 

1448 def clearMode(self,mode_bit): 

1449 mask= ~ mode_bit 

1450 self.printer_mode= self.printer_mode & mask 

1451 

1452 def isMode(self,mode_bit): 

1453 if (self.printer_mode & mode_bit): 

1454 return True 

1455 else: 

1456 return False 

1457# 

1458# process barcodes 

1459# 

1460 def add_bar(self,length,fill): 

1461 for i in range(length): 

1462 if len(self.bcline)== PRINTER_CHARACTER_HEIGHT_PIXELS: 

1463 self.bclist.append(self.bcline) 

1464 self.bcline= [] 

1465 if fill: 

1466 self.bcline.append(1) 

1467 else: 

1468 self.bcline.append(0) 

1469 

1470 def process_barcodes(self): 

1471 

1472 self.bclist= [] 

1473 self.bcline= [] 

1474 self.add_bar(3,True) 

1475 self.add_bar(3,False) 

1476 self.add_bar(3,True) 

1477 self.add_bar(3,False) 

1478 for i in range (self.printer_buffer.length()): 

1479 ret= self.printer_buffer.get(i) 

1480 code=ret[0] 

1481 b= 128 

1482 for j in range(8): 

1483 if b & code: 

1484 self.add_bar(6,True) 

1485 else: 

1486 self.add_bar(3,True) 

1487 self.add_bar(3,False) 

1488 b= b // 2 

1489 self.add_bar(6,True) 

1490 self.add_bar(3,False) 

1491 self.add_bar(3,True) 

1492 while len(self.bcline)< PRINTER_CHARACTER_HEIGHT_PIXELS: 

1493 self.add_bar(1,False) 

1494 self.bclist.append(self.bcline) 

1495 return 

1496# 

1497# add column to line buffer 

1498# 

1499 def add_column(self,c,mode): 

1500# 

1501# put column data into line buffer 

1502# 

1503 self.line_buffer.add(c,mode,False) 

1504 if mode & mode_doublewide: 

1505 self.line_buffer.add(c,mode,False) 

1506 

1507# 

1508# generate character in line buffer 

1509# 

1510 def add_char(self,c,mode): 

1511# 

1512# blank is wrap position 

1513# 

1514 wrap=False 

1515 if c== 0x20: 

1516 wrap=True 

1517# 

1518# in lowercase mode convert uppercase chars 

1519# 

1520 if (mode & mode_lowercase) and (c >=0x41 and c <= 0x5A): 

1521 c+=0x20 

1522# 

1523# leading space 

1524# 

1525 self.line_buffer.add(0,mode,wrap) 

1526 if mode & mode_doublewide: 

1527 self.line_buffer.add(0,mode,False) 

1528# 

1529# get bitmap, handle double wide 

1530# 

1531 for col in range(0,5): 

1532 col_data=self.char_gen.get(c, col) 

1533 self.line_buffer.add(col_data,mode,False) 

1534 if mode & mode_doublewide: 

1535 self.line_buffer.add(col_data,mode,False) 

1536# 

1537# trailing space 

1538# 

1539 self.line_buffer.add(0,mode,False) 

1540 if mode & mode_doublewide: 

1541 self.line_buffer.add(0,mode,False) 

1542 return True 

1543 

1544# 

1545# end of line, process buffer 

1546# 

1547 def process_line(self): 

1548 

1549 buffer_idx=0 

1550 fmtpos= self.printer_buffer.fmtpos() 

1551 log_line="" 

1552# 

1553# right justify buffer if we do not have a format specifier 

1554# 

1555 if (self.isMode(mode_rjust) and fmtpos<0): 

1556 shift= PRINTER_WIDTH - self.printer_buffer.pxlen() 

1557 for i in range(shift): 

1558 self.add_column(0,0) 

1559# 

1560# center, if format specifier is at the beginning or the end of the buffer 

1561# 

1562 if fmtpos >=0: 

1563 if fmtpos==0 or fmtpos== self.printer_buffer.length()-2: 

1564 freecols=PRINTER_WIDTH - self.printer_buffer.pxlen() 

1565 shift= freecols//2 

1566 if freecols % 2 == 1: 

1567 shift+=1 

1568 for i in range(shift): 

1569 self.add_column(0,0) 

1570 fmtpos= -1 

1571# 

1572# output content 

1573# 

1574 while buffer_idx < self.printer_buffer.length(): 

1575 ret= self.printer_buffer.get(buffer_idx) 

1576 v= ret[0] 

1577 t= ret[1] 

1578 m= ret[2] 

1579# 

1580# check if we have spacing format specifier right in the middle 

1581# 

1582 if fmtpos >=0: 

1583 if buffer_idx== fmtpos: 

1584 freecols=PRINTER_WIDTH - self.printer_buffer.pxlen() 

1585 for i in range(freecols): 

1586 self.add_column(0,0) 

1587 fmtpos= -1 

1588# 

1589# add character to line buffer 

1590# 

1591 if t== type_char: 

1592 self.add_char(v,m) 

1593 if self.isMode(mode_8bit): 

1594 log_line+= charconv(chr(v),CHARSET_HP41) 

1595 else: 

1596 log_line+= charconv(chr(v),CHARSET_ROMAN8) 

1597# 

1598# add column to line buffer 

1599# 

1600 if t== type_column: 

1601 self.add_column(v,m) 

1602# 

1603# generate blank characters or blank columns to line buffer 

1604# 

1605 if t== type_skip: 

1606 if v >= 0xa0 and v <= 0xb7: 

1607 n= v-0xa0 

1608 for i in range(n): 

1609 self.add_char(0x20,m) 

1610 if v >= 0xb8 and v <= 0xbf: 

1611 n=v-0xb8 

1612 for i in range(n): 

1613 self.add_column(0,m) 

1614 buffer_idx+=1 

1615# 

1616# send line buffer to GUI 

1617# 

1618 self.line_buffer.prt() 

1619# 

1620# send log output to GUI 

1621# 

1622 if log_line !="": 

1623 log_line+="\n" 

1624 self.guiobject.put_cmd([REMOTECMD_LOG,log_line]) 

1625# 

1626# clear line buffer and printer buffer 

1627# 

1628 self.line_buffer.clear() 

1629 self.printer_buffer.clear() 

1630# 

1631# update status information 

1632# 

1633 self.set_status(STA_EL) 

1634 self.set_status(STA_BE) 

1635# 

1636# process escape sequences 

1637# 

1638 def process_esc(self): 

1639# 

1640# switch to 8 bit mode 

1641# 

1642 if self.esc_seq=="|": 

1643 self.setMode(mode_8bit) 

1644 self.set_status(STA_EB) 

1645 self.char_gen.set_charset(CHARSET_ALTERNATE) 

1646 return 

1647# 

1648# single width 

1649# 

1650 elif self.esc_seq=="&k0S": 

1651 self.clearMode(mode_doublewide) 

1652 self.clear_status(STA_DW) 

1653 return 

1654# 

1655# double width 

1656# 

1657 elif self.esc_seq=="&k1S": 

1658 self.setMode(mode_doublewide) 

1659 self.set_status(STA_DW) 

1660 return 

1661# 

1662# left justify 

1663# 

1664 elif self.esc_seq=="&l0J": 

1665 self.clearMode(mode_rjust) 

1666 self.clear_status(STA_RJ) 

1667 return 

1668# 

1669# right justify 

1670# 

1671 elif self.esc_seq=="&l1J": 

1672 self.setMode(mode_rjust) 

1673 self.set_status(STA_RJ) 

1674 return 

1675# 

1676# Graphic 

1677# 

1678 elif self.esc_seq.startswith("*b") and self.esc_seq.endswith("G"): 

1679 ret=re.findall(r"\d+",self.esc_seq) 

1680 if ret== []: 

1681 return 

1682 try: 

1683 n=int(ret[0]) 

1684 except ValueError: 

1685 return 

1686 if n<0 or n> 255: 

1687 return 

1688 self.num_graphics=n 

1689 return 

1690# 

1691# barcode 

1692# 

1693 elif self.esc_seq.startswith("*z") and self.esc_seq.endswith("B"): 

1694 ret=re.findall(r"\d+",self.esc_seq) 

1695 if ret== []: 

1696 return 

1697 try: 

1698 n=int(ret[0]) 

1699 except ValueError: 

1700 return 

1701 if n<0 or n> 16: 

1702 return 

1703 self.num_barcode=n 

1704 return 

1705# 

1706# format 

1707# 

1708 elif self.esc_seq=="&l2J": 

1709 self.printer_buffer.add(0,type_format,self.printer_mode) 

1710 self.printer_buffer.add(0,type_format,self.printer_mode) 

1711 return 

1712# 

1713# skip characters 

1714# 

1715 elif self.esc_seq.startswith("&a+") and self.esc_seq.endswith("C"): 

1716 ret=re.findall(r"\d+",self.esc_seq) 

1717 if ret== []: 

1718 return 

1719 try: 

1720 n=int(ret[0]) 

1721 except ValueError: 

1722 return 

1723 if n<0 or n> 23: 

1724 return 

1725 n+= 0xa0 

1726 self.printer_buffer.add(n,type_skip,self.printer_mode) 

1727 return 

1728# 

1729# skip columns 

1730# 

1731 elif self.esc_seq.startswith("&a+") and self.esc_seq.endswith("D"): 

1732 ret=re.findall(r"\d+",self.esc_seq) 

1733 if ret== []: 

1734 return 

1735 try: 

1736 n=int(ret[0]) 

1737 except ValueError: 

1738 return 

1739 if n<0 or n> 7: 

1740 return 

1741 n+= 0xb8 

1742 self.printer_buffer.add(n,type_skip,self.printer_mode) 

1743 return 

1744# 

1745# skip absolute 

1746# 

1747 elif self.esc_seq.startswith("&a") and self.esc_seq.endswith("D"): 

1748 ret=re.findall(r"\d+",self.esc_seq) 

1749 if ret== []: 

1750 return 

1751 try: 

1752 n=int(ret[0]) 

1753 except ValueError: 

1754 return 

1755 if n<0 or n> 168: 

1756 return 

1757 skip=n-self.printer_buffer.pxlen() 

1758 if n<=0: 

1759 return 

1760 skip_chars= skip // PRINTER_CHARACTER_WIDTH_PIXELS 

1761 n= skip_chars+ 0xa0 

1762 self.printer_buffer.add(n,type_skip,self.printer_mode) 

1763 skip_columns= skip % PRINTER_CHARACTER_WIDTH_PIXELS 

1764 n= skip_columns+ 0xb8 

1765 self.printer_buffer.add(n,type_skip,self.printer_mode) 

1766 return 

1767# 

1768# nonparse mode 

1769# 

1770 elif self.esc_seq=="&k0H": 

1771 self.clearMode(mode_parse) 

1772 return 

1773# 

1774# parse mode 

1775# 

1776 elif self.esc_seq=="&k1H": 

1777 self.setMode(mode_parse) 

1778 return 

1779 return 

1780# 

1781# main printer data processing method 

1782# 

1783 def process_char(self,ch): 

1784# 

1785# barcode mode, accumulate code numbers to buffer 

1786# 

1787 if self.num_barcode > 0: 

1788 self.printer_buffer.add(ch,type_barcode,self.printer_mode) 

1789 self.num_barcode-=1 

1790# 

1791# all barcodes read, process line 

1792# 

1793 if self.num_barcode==0: 

1794 self.process_barcodes() 

1795 return 

1796# 

1797# graphics mode (ESC mode only), add columns to buffer 

1798# 

1799 if self.num_graphics > 0: 

1800 self.printer_buffer.add(ch,type_column,self.printer_mode) 

1801 self.num_graphics-=1 

1802 return 

1803# 

1804# process ESC sequences 

1805# 

1806 if (self.esc== False) and (ch== 0x1B) and not self.isMode(mode_8bit): 

1807 self.esc= True 

1808 self.esc_seq="" 

1809 self.esc_prefix="" 

1810 return 

1811 if self.esc: 

1812# 

1813# ESC | or escape sequence terminated with capital letter 

1814# 

1815# if ch == 0x7c or (ch >= 0x41 and ch <= 0x5A): 

1816 if chr(ch) in "|CDHSJGB": 

1817 self.esc_seq+= chr(ch) 

1818 if self.esc_prefix!="": 

1819 self.esc_seq= self.esc_prefix+self.esc_seq 

1820 self.process_esc() 

1821 self.esc= False 

1822 self.esc_seq="" 

1823 self.esc_prefix="" 

1824 return 

1825# 

1826# repeated escape sequence terminated with lowercase letter 

1827# unfortunately b occurs in two escape sequences at different positions 

1828# 

1829 if chr(ch) in "cdhsjgb" and len(self.esc_seq)>2: 

1830 if self.esc_prefix == "": 

1831 self.esc_prefix= self.esc_seq[:2] 

1832 self.esc_seq= self.esc_seq[2:] 

1833 self.esc_seq= self.esc_prefix+self.esc_seq+chr(ch).upper() 

1834 self.process_esc() 

1835 self.esc_seq="" 

1836 return 

1837# 

1838# still in escape sequence, accumulate characters 

1839#  

1840 self.esc_seq+= chr(ch) 

1841 return 

1842# 

1843# not in escape sequence, everything goes to the printer buffer now 

1844# 

1845# 

1846# ignore line feed 

1847# 

1848 if ch== 0x0A and not self.isMode(mode_column): 

1849 return 

1850# 

1851# cr is end of line 

1852# 

1853 if ch == 0x0D and not self.isMode(mode_column): 

1854 self.process_line() 

1855 return 

1856# 

1857# do normal processing: 8bit and escape mode 

1858# 

1859 if self.isMode(mode_8bit): 

1860# 

1861# normal character or column 

1862# 

1863 if ch <= 0x7F: 

1864 self.clear_status(STA_EL) 

1865 self.clear_status(STA_BE) 

1866 if self.isMode(mode_column): 

1867 self.printer_buffer.add(ch,type_column,self.printer_mode) 

1868 else: 

1869 self.printer_buffer.add(ch,type_char,self.printer_mode) 

1870# 

1871# barcode (only valid in column mode, this is not handled here) 

1872# buffers are reset 

1873# 

1874 elif ch >= 0x80 and ch <= 0x8F: 

1875 self.num_barcode= ch - 0x7F 

1876 self.printer_buffer.clear() 

1877 self.line_buffer.clear() 

1878# 

1879# skip characters 

1880# 

1881 elif ch >= 0xA0 and ch <= 0xB7: 

1882 self.printer_buffer.add(ch,type_skip,self.printer_mode) 

1883# 

1884# skip columns 

1885# 

1886 elif ch >= 0xB8 and ch <= 0xBF: 

1887 self.printer_buffer.add(ch,type_skip,self.printer_mode) 

1888# 

1889# format specifier (2 characters to read) 

1890# 

1891 elif ch== 0xC0: 

1892 self.printer_buffer.add(0,type_format,self.printer_mode) 

1893 self.printer_buffer.add(0,type_format,self.printer_mode) 

1894# 

1895# select width, upper/lowercase, character/column mode 

1896# bit0 is lowercase flag 

1897# bit1 is column mode flag 

1898# bit2 is double wide flag 

1899# bit3 is used, but unknown to me (Parse mode?) 

1900# 

1901 elif ch >= 0xD0 and ch <= 0xDF: 

1902 if ch & 0x01: 

1903 self.setMode(mode_lowercase) 

1904 self.set_status(STA_LC) 

1905 else: 

1906 self.clearMode(mode_lowercase) 

1907 self.clear_status(STA_LC) 

1908 if ch & 0x02: 

1909 self.setMode(mode_column) 

1910 self.set_status(STA_CO) 

1911 else: 

1912 self.clearMode(mode_column) 

1913 self.clear_status(STA_CO) 

1914 if ch & 0x04: 

1915 self.setMode(mode_doublewide) 

1916 self.set_status(STA_DW) 

1917 else: 

1918 self.clearMode(mode_doublewide) 

1919 self.clear_status(STA_DW) 

1920 

1921# 

1922# left justify 

1923# 

1924 elif ch== 0xE0: 

1925 self.clearMode(mode_rjust) 

1926 self.clear_status(STA_RJ) 

1927# 

1928# right justify 

1929# 

1930 elif ch== 0xE8: 

1931 self.setMode(mode_rjust) 

1932 self.set_status(STA_RJ) 

1933# 

1934# escape mode 

1935# 

1936 elif ch== 0xFC: 

1937 self.clearMode(mode_8bit) 

1938 self.clear_status(STA_EB) 

1939 self.char_gen.set_charset(CHARSET_ASCII) 

1940# 

1941# allow paper advance 

1942# 

1943 elif ch== 0xFE: 

1944 self.clearMode(mode_inhibit_advance) 

1945# 

1946# inhibit paper advance 

1947# 

1948 elif ch== 0xFF: 

1949 self.setMode(mode_inhibit_advance) 

1950# 

1951# unknown 8 bit command 

1952# 

1953 else: 

1954 pass 

1955# 

1956# escape mode 

1957# 

1958 else: 

1959 if ch< 0x80: 

1960 self.printer_buffer.add(ch,type_char,self.printer_mode) 

1961 

1962# 

1963# HP-IL device status bits 

1964# 

1965 def set_status(self,bitmask): 

1966 s= self.pildevice.get_status() 

1967 s= s | bitmask 

1968 self.pildevice.set_status(s) 

1969 return 

1970 

1971 def clear_status(self,bitmask): 

1972 s= self.pildevice.get_status() 

1973 s= s & ( ~ bitmask) 

1974 self.pildevice.set_status(s) 

1975 return 

1976 

1977 def get_status(self,bitmask): 

1978 s= self.pildevice.get_status() 

1979 return(s & bitmask) 

1980# 

1981# process commands sent from the GUI 

1982# 

1983 def process(self,command): 

1984 

1985 if command== CMD_MAN: 

1986 self.clear_status(STA_MB) 

1987 self.clear_status(STA_MA) 

1988 return 

1989 if command== CMD_NORM: 

1990 self.set_status(STA_MB) 

1991 self.clear_status(STA_MA) 

1992 return 

1993 if command== CMD_TRACE: 

1994 self.clear_status(STA_MB) 

1995 self.set_status(STA_MA) 

1996 return 

1997 if command== CMD_PRINT_PRESSED: 

1998 self.set_status(STA_SR) 

1999 self.set_status(STA_PR) 

2000 return 

2001 if command== CMD_ADV_PRESSED: 

2002 if not self.isMode(mode_inhibit_advance): 

2003 self.set_status(STA_SR) 

2004 self.set_status(STA_PA) 

2005 return 

2006 if command== CMD_PRINT_RELEASED: 

2007 self.clear_status(STA_SR) 

2008 self.clear_status(STA_PR) 

2009 return 

2010 if command== CMD_ADV_RELEASED: 

2011 if not self.isMode(mode_inhibit_advance): 

2012 self.clear_status(STA_SR) 

2013 self.clear_status(STA_PA) 

2014 return 

2015 if command== CMD_CLEAR: 

2016 return 

2017 

2018# 

2019# HP-IL virtual HP82162A object class --------------------------------------- 

2020# 

2021 

2022 

2023class cls_pilhp82162a(cls_pildevbase): 

2024 

2025 def __init__(self,guiobject): 

2026 super().__init__() 

2027 

2028# 

2029# overloaded variable initialization 

2030# 

2031 self.__aid__ = 0x20 # accessory id  

2032 self.__defaddr__ = 1 # default address alter AAU 

2033 self.__did__ = "" # device id 

2034 self.__status_len__=2 # device status is 2 bytes 

2035# 

2036# object specific variables 

2037# 

2038 self.__guiobject__= guiobject 

2039# 

2040# initialize remote command queue and lock 

2041# 

2042 self.__print_queue__= queue.Queue() 

2043 self.__print_queue_lock__= threading.Lock() 

2044# 

2045# printer processor 

2046# 

2047 self.__printer__=cls_special_k(self,self.__guiobject__) 

2048 

2049# 

2050# public (overloaded) -------- 

2051# 

2052# enable: reset 

2053# 

2054 def enable(self): 

2055 self.__printer__.reset() 

2056 return 

2057# 

2058# disable: clear the printer command queue 

2059# 

2060 def disable(self): 

2061 self.__print_queue_lock__.acquire() 

2062 while True: 

2063 try: 

2064 self.__print_queue__.get_nowait() 

2065 self.__print_queue__.task_done() 

2066 except queue.Empty: 

2067 break 

2068 self.__print_queue_lock__.release() 

2069# 

2070# process frames  

2071# 

2072 def process(self,frame): 

2073 

2074 if self.__isactive__: 

2075 self.process_print_queue() 

2076 frame= super().process(frame) 

2077 return frame 

2078# 

2079# process the printer command queue 

2080# 

2081 def process_print_queue(self): 

2082 items=[] 

2083 self.__print_queue_lock__.acquire() 

2084 while True: 

2085 try: 

2086 i=self.__print_queue__.get_nowait() 

2087 items.append(i) 

2088 self.__print_queue__.task_done() 

2089 except queue.Empty: 

2090 break 

2091 self.__print_queue_lock__.release() 

2092 if len(items): 

2093 for c in items: 

2094 self.__printer__.process(c) 

2095 return 

2096 

2097# 

2098# put command into the print-command queue 

2099# 

2100 def put_cmd(self,item): 

2101 self.__print_queue_lock__.acquire() 

2102 self.__print_queue__.put(item) 

2103 self.__print_queue_lock__.release() 

2104# 

2105# set status (2 byte status information) 

2106# 

2107 def set_status(self,s): 

2108 self.__setstatus__(s) 

2109 return s 

2110# 

2111# get status byte (2 byte status information) 

2112# 

2113 def get_status(self): 

2114 s=self.__getstatus__() 

2115 return s 

2116 

2117# 

2118# private (overloaded) -------- 

2119# 

2120# 

2121# output character to HP82162A 

2122# 

2123 def __indata__(self,frame): 

2124 self.__printer__.process_char(frame & 0xFF) 

2125 

2126# 

2127# clear device: reset printer 

2128# 

2129 def __clear_device__(self): 

2130 super().__clear_device__() 

2131# 

2132# clear printer queue 

2133# 

2134 self.__print_queue_lock__.acquire() 

2135 while True: 

2136 try: 

2137 self.__print_queue__.get_nowait() 

2138 self.__print_queue__.task_done() 

2139 except queue.Empty: 

2140 break 

2141 self.__print_queue_lock__.release() 

2142# 

2143# reset device  

2144# 

2145 self.__printer__.reset() 

2146