1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
|
implementation module osprint
import StdArray, StdBool, StdEnum, StdFile, StdFunc, StdInt, StdList, StdMisc, StdTuple
import clCCall_12,clCrossCall_12, iostate, scheduler
import ospicture, osevent, StdWindow, StdPSt
import code from "cCrossCallPrinter_121.o",
"cprinter_121.o"
:: PrintSetup
= { devmode :: !String
, device :: !String // device, driver & output strings are null terminated
, driver :: !String
, output :: !String
}
:: JobInfo
= { range :: !(!Int,!Int)
, copies :: !Int
}
:: PrintInfo
= { printSetup :: PrintSetup
, jobInfo :: JobInfo
}
:: Alternative x y
= Cancelled x
| StartedPrinting y
os_installprinter :: !*OSToolbox -> *OSToolbox
os_installprinter _
= code
{
.inline InstallCrossCallPrinter
ccall InstallCrossCallPrinter "I-I"
.end
}
os_getpagedimensions :: !PrintSetup !Bool -> (!(!Int,!Int), !(!(!Int,!Int),!(!Int,!Int)), !(!Int,!Int))
os_getpagedimensions { devmode, device, driver } emulateScreenRes
= os_getpagedimensionsC devmode device driver emulateScreenRes
os_defaultprintsetup :: !*env -> (!PrintSetup, !*env)
os_defaultprintsetup env
# (dmSize,printerHandle,device,driver,output,env) = getDevmodeSizeC env
| dmSize==0
= ({devmode="\0", device="\0", driver="\0", output="\0"},env)
# devmode = createArray dmSize ' '
devmode = { devmode & [dec dmSize]='\0'}
env = getDefaultDevmodeC devmode printerHandle device env // alters contents of printSetup
= ({devmode=devmode, device=device, driver=driver, output=output}, env)
printSetupDialogBoth :: !PrintSetup !(Maybe *Context) -> (!PrintSetup, !Maybe *Context)
printSetupDialogBoth print_setup=:{devmode,device,driver,output} mb_context
# (os, mb_context) = EnvGetOS mb_context
# os = os_installprinter os
# (devmodePtr,os) = winMakeCString devmode os
# (devicePtr, os) = winMakeCString device os
# (driverPtr, os) = winMakeCString driver os
# (outputPtr, os) = winMakeCString output os
# (ok, pdPtr, mb_context, os) = CCPrintSetupDialog mb_context (size devmode) devmodePtr devicePtr driverPtr outputPtr os
# os = winReleaseCString devmodePtr os
# os = winReleaseCString devicePtr os
# os = winReleaseCString driverPtr os
# os = winReleaseCString outputPtr os
| ok==0
# os = release_memory_handles pdPtr os
= (print_setup, EnvSetOS os mb_context)
| otherwise
# ((ndevmode,ndevice,ndriver,noutput),os)
= get_printSetup_with_PRINTDLG pdPtr os
# os = release_memory_handles pdPtr os
= ({devmode=ndevmode,device=ndevice,driver=ndriver,output=noutput}, EnvSetOS os mb_context)
os_printsetupvalid :: !PrintSetup !*env -> (!Bool, !*env)
os_printsetupvalid {devmode,device,driver} env
= os_printsetupvalidC devmode device driver env
os_printsetupvalidC :: !String !String !String!*env -> (!Bool, !*env)
os_printsetupvalidC _ _ _ _
= code
{
ccall os_printsetupvalidC "SSS:I:A"
}
class PrintEnvironments printEnv where
os_printpageperpage :: !Bool !Bool
!.x
.(.x -> .(PrintInfo -> .(*Picture -> *((.Bool,Point2),*(.state,*Picture)))))
(*(.state,*Picture) -> *((.Bool,Point2),*(.state,*Picture)))
!PrintSetup !*printEnv
-> (Alternative .x .state,!*printEnv)
os_printsetupdialog :: !PrintSetup !*printEnv
-> (!PrintSetup,!*printEnv)
instance PrintEnvironments (PSt .l) where
os_printpageperpage doDialog emulateScreen x initFun transFun printSetup pSt=:{io}
#! (windowStack, io) = getWindowStack io
windowStackIds = map fst windowStack
(zippedWithSelectState, io) = seqList (map zipWithSelectState windowStackIds) io
activeWindowIds = [ id \\ (mbSelectState, id) <- zippedWithSelectState | isEnabled mbSelectState]
io = seq (map disableWindow activeWindowIds) io
(result, pSt) = accContext accFun { pSt & io=io }
pSt = appPIO (seq (map enableWindow activeWindowIds)) pSt
= (result, pSt)
where
accFun context
# (os, context) = EnvGetOS context
# os = os_installprinter os
# (x,mb_context,os) = printPagePerPageBothSemaphor
doDialog emulateScreen x initFun transFun printSetup (Just context) os
= (x,EnvSetOS os (fromJust mb_context))
zipWithSelectState :: Id (IOSt .l) -> (v:(Maybe SelectState,Id),IOSt .l)
zipWithSelectState id io
#! (mbSelectState, io) = getWindowSelectState id io
= ((mbSelectState, id), io)
isEnabled (Just Able) = True
isEnabled _ = False
os_printsetupdialog printSetup pSt
= accContext (accFun printSetup) pSt
where
accFun printSetup context
# (printSetup, Just context) = printSetupDialogBoth printSetup (Just context)
= (printSetup, context)
instance PrintEnvironments Files where
os_printpageperpage doDialog emulateScreen x initFun transFun printSetup files
# (os, files) = EnvGetOS files
# os = os_installprinter os
# (x,_,os) = printPagePerPageBothSemaphor
doDialog emulateScreen x initFun transFun printSetup Nothing os
= (x, EnvSetOS os files)
os_printsetupdialog printSetup files
# (printSetup, _) = printSetupDialogBoth printSetup Nothing
= (printSetup, files) // oh lala
printPagePerPageBothSemaphor :: !Bool !Bool .a
.(.a -> .(.PrintInfo -> .(*Picture -> *((Bool,Origin),*(.b,*Picture)))))
(*(.b,*Picture) -> *((Bool,Origin),*(.b,*Picture)))
!PrintSetup *(Maybe *Context) !*OSToolbox
-> *(*(Alternative .a .b),*(Maybe *Context),!*OSToolbox)
printPagePerPageBothSemaphor p1 p2 x p4 p5 printSetup mb_context os
// with this mechanism it is assured, that only one print job can happen at a time
// addSemaphor adds the parameter to a C global and gives back the previous value of that
// global
# (s,os) = addSemaphor 1 os
| s>0
# (_,os) = addSemaphor (-1) os
= (Cancelled x,mb_context,os)
# (result,mb_context,os) = printPagePerPageBoth p1 p2 x p4 p5 printSetup mb_context os
(_,os) = addSemaphor (-1) os
= (result,mb_context,os)
printPagePerPageBoth :: !Bool !Bool .a
.(.a -> .(.PrintInfo -> .(*Picture -> *((Bool,Origin),*(.b,*Picture)))))
(*(.b,*Picture) -> *((Bool,Origin),*(.b,*Picture)))
PrintSetup *(Maybe *Context) !*OSToolbox
-> *(*(Alternative .a .b),*(Maybe *Context),!*OSToolbox)
printPagePerPageBoth doDialog emulateScreen x initFun transFun printSetup mb_context os
// do the print dialog (or not) and get the hdc and the printInfo
# (err, hdc, printInfo, mb_context, os)
= getPrintInfo doDialog emulateScreen printSetup mb_context os
| err == 4107 // this error occurs, when the printsetup contains bad values
# (defaultPS, os) = os_defaultprintsetup os
= printPagePerPageBoth doDialog emulateScreen x initFun transFun defaultPS mb_context os
// check, whether the user canceled
| err >= 0 = (Cancelled x, mb_context, os)
// call StartDoc either via the OS thread or direct
# (err, mb_context, os) = CCstartDoc hdc mb_context os
| err <= 0 = (Cancelled x, mb_context, deleteDC hdc os)
// user canceled printing to file from file dialog
// initialise printer picture and call the initFun function
# picture = initPicture zeroOrigin (hdc,os)
(endOrig,(initState,picture)) = initFun x printInfo picture
(_,_,_,hdc,os) = unpackPicture picture
// now print all pages
# (finalState,hdc,mb_context,os)
= printPages 0 transFun endOrig initState hdc mb_context os
// Sluit af
(mb_context, os) = CCendDoc hdc mb_context os
= (StartedPrinting finalState, mb_context, (deleteDC hdc os))
printPages :: Int
(*(.a,*Picture) -> *((Bool,Origin),* (.a,*Picture)))
(Bool,Origin) .a HDC *(Maybe *Context) !*OSToolbox
-> *(.a,HDC,*(Maybe *Context),!*OSToolbox)
printPages _ _ (True,_) state hdc mb_context os
=(state,hdc,mb_context,os)
printPages pageNr fun (_,origin) state hdc mb_context os
// give OS thread eventually a chance to handle events
# (mb_context,os) = evtlSwitchToOS pageNr hdc mb_context os
# (ok, os) = startPage hdc os
| ok == 0 = abort "\nPrint08: Failed in \"StartPage\". Probably not enough memory."
# picture = initPicture origin (hdc,os)
// apply drawfunctions contained in this page
((endOfDoc,nextOrigin),(state`,picture)) = fun (state,picture)
// finish drawing
# (_,_,_,hdc,os) = unpackPicture picture
(ok, os) = endPage hdc os
// (not ok) should not cause an abort, because endPage returns an error, when user chooses
// "encapsulated postscript" as output format and the output is longer than one page.
// This situation can't be retrieved from the "GetLastError" code. An abort should not occur.
(canceled,os) = wasCanceled os
// draw rest of pages
= printPages (inc pageNr) fun (endOfDoc || canceled || (ok==0),nextOrigin) state` hdc mb_context os
zeroOrigin :== zero
///////////////////////////////////////////////////////////////////////////////
getPrintInfo :: !.Bool !.Bool .PrintSetup *(Maybe *Context) !*OSToolbox
-> *(Int,Int,.PrintInfo,*Maybe *Context,!.OSToolbox);
getPrintInfo doDialog emulateScreen {devmode, device, driver, output} mb_context os
# (devmodePtr,os) = winMakeCString devmode os
(devicePtr,os) = winMakeCString device os
(driverPtr,os) = winMakeCString driver os
(outputPtr,os) = winMakeCString output os
( err, data, pdPtr, mb_context, os)
= CCgetDC (if doDialog 1 0) (if emulateScreen 2 0) // these two bits will be packed into one word in CCgetDC
(size devmode) devmodePtr devicePtr driverPtr outputPtr mb_context os
os = winReleaseCString devmodePtr os
os = winReleaseCString devicePtr os
os = winReleaseCString driverPtr os
os = winReleaseCString outputPtr os
| doDialog && (err==(-1))
# (setup_strings, os) = get_printSetup_with_PRINTDLG pdPtr os
os = release_memory_handles pdPtr os
= continuation err data mb_context (setup_strings, os)
= continuation err data mb_context ((devmode,device,driver,output),os)
where
continuation err (first,last,copies,hdc) mb_context ((devmode,device,driver,output),os)
# first` = max 1 first
last` = max first` last
copies` = max 1 copies
= ( err,
hdc,
{ printSetup = { devmode=devmode, device=device ,driver=driver, output=output },
jobInfo = { range = (first`,last`),
copies = copies`
}
},
mb_context,
os
)
handleContextOSEvent` :: !OSEvent !Context !*OSToolbox -> (!CrossCallInfo,!Context,!*OSToolbox)
handleContextOSEvent` osEvent context tb
# (return,context) = handleContextOSEvent osEvent context
= (setReplyInOSEvent return,context,tb)
CCgetDC :: !.Int !.Int !.Int !.Int !.Int !.Int !.Int !*(Maybe *Context) !*OSToolbox -> *(!Int,!(!Int,!Int,!Int,!Int),!Int,!*Maybe *Context,!.OSToolbox);
CCgetDC doDialog emulateScreen devmodeSize devmodePtr devicePtr driverPtr outputPtr Nothing os
# (ok,first,last,copies,pdPtr,deviceContext,os)
= getDC doDialog emulateScreen 1 devmodeSize devmodePtr devicePtr driverPtr outputPtr os
= (ok,(first,last,copies,deviceContext),pdPtr,Nothing,os)
CCgetDC doDialog emulateScreen devmodeSize devmodePtr devicePtr driverPtr outputPtr (Just context) os
# createcci = Rq6Cci CcRqGET_PRINTER_DC (doDialog bitor emulateScreen) devmodeSize
devmodePtr devicePtr driverPtr outputPtr
# (rcci, context, os) = issueCleanRequest handleContextOSEvent` createcci context os
= ( rcci.p1, (rcci.p2, rcci.p3, rcci.p4,rcci.p6), rcci.p5,
////////err, (first, last, copies, deviceContext),pdPtr,
Just context,os
)
CCPrintSetupDialog :: !(Maybe *Context) !.Int !.Int !.Int !.Int !.Int !*OSToolbox -> (!OkReturn,!Int,!Maybe *Context, !.OSToolbox);
CCPrintSetupDialog nothing=:Nothing devmodeSize devmodePtr devicePtr driverPtr outputPtr os
# (ok, pdPtr, os) = printSetup 1 devmodeSize devmodePtr devicePtr driverPtr outputPtr os
= (ok, pdPtr, nothing, os)
CCPrintSetupDialog (Just context) devmodeSize devmodePtr devicePtr driverPtr outputPtr os
# createcci = Rq5Cci CcRqDO_PRINT_SETUP devmodeSize devmodePtr devicePtr driverPtr outputPtr
(rcci, context, os) = issueCleanRequest handleContextOSEvent` createcci context os
= (rcci.p1, rcci.p2, Just context, os)
/* MW was
CCPrintSetupDialog :: !.Bool .Int .Int .Int .Int .Int !*OSToolbox -> (OkReturn,Int,!.OSToolbox);
CCPrintSetupDialog True devmodeSize devmodePtr devicePtr driverPtr outputPtr os
= printSetup 1 devmodeSize devmodePtr devicePtr driverPtr outputPtr os
CCPrintSetupDialog False devmodeSize devmodePtr devicePtr driverPtr outputPtr os
# createcci = Rq5Cci CcRqDO_PRINT_SETUP devmodeSize devmodePtr devicePtr driverPtr outputPtr
(rcci, os) = issueCleanRequest2 (ErrorCallback2 "ERROR in osPrint08") createcci os
(rcci, os) = issueCleanRequest2 handleContextOSEvent` createcci os
= (rcci.p1, rcci.p2, os)
*/
CCstartDoc :: !.HDC !*(Maybe *Context) !*OSToolbox -> *(!Int,!*Maybe *Context,!*OSToolbox)
// error code: -1:no error, 0: user canceled file dialog, others: other error
CCstartDoc hdc Nothing os
# (err,os) = startDoc hdc os
= (err,Nothing,os)
CCstartDoc hdc (Just context) os
# createcci = Rq1Cci CcRqSTARTDOC hdc
(rcci,context, os) = issueCleanRequest handleContextOSEvent` createcci context os
= (rcci.p1, Just context, os)
CCendDoc :: !.HDC !*(Maybe *Context) !*OSToolbox -> *(!*Maybe *Context,!*OSToolbox)
CCendDoc hdc Nothing os
# os = endDoc hdc os
= (Nothing,os)
CCendDoc hdc (Just context) os
# createcci = Rq1Cci CcRqENDDOC hdc
(_,context, os) = issueCleanRequest handleContextOSEvent` createcci context os
= (Just context,os)
evtlSwitchToOS :: !Int !.Int !*(Maybe *Context) !*OSToolbox -> *(!*Maybe *Context,!.OSToolbox)
evtlSwitchToOS _ _ Nothing os
= (Nothing,os)
evtlSwitchToOS pageNr hdc (Just context) os
# nrStr = toString pageNr
# messageText = if (pageNr==0) ""
(nrStr+++" page"+++(if (pageNr==1) "" "s")+++" printed")
# (textPtr,os) = winMakeCString messageText os
# createcci = Rq1Cci CcRqDISPATCH_MESSAGES_WHILE_PRINTING textPtr
# (_,context, os) = issueCleanRequest handleContextOSEvent` createcci context os
# os = winReleaseCString textPtr os
= (Just context, os)
initPicture :: !.Origin !*(!.OSPictContext,!*OSToolbox) -> *Picture
initPicture origin intPict
= packPicture origin defaultPen False (fst intPict) (snd intPict)
EnvGetOS :: !*env -> (!*OSToolbox,!*env)
EnvGetOS env
= (42,env)
EnvSetOS :: !*OSToolbox !*env -> *env
EnvSetOS os env
= env
//////////////////////////////////////////////////
// //
// C CALLING FUNCTIONS //
// //
//////////////////////////////////////////////////
:: OkReturn :== Int // okReturn<>0 <=> ok !
os_getpagedimensionsC :: !String !String !String !Bool
-> (!(!Int,!Int), !(!(!Int,!Int),!(!Int,!Int)), !(!Int,!Int))
os_getpagedimensionsC _ _ _ _
= code
{
ccall os_getpagedimensionsC "SSSI-IIIIIIII"
}
getDevmodeSizeC :: !*env -> (!Int,!Int,!String,!String,!String,!*env)
getDevmodeSizeC _
= code
{
ccall getDevmodeSizeC ":VIISSS:A"
}
getDefaultDevmodeC :: !String !Int !String !*env -> *env
getDefaultDevmodeC _ _ _ _
= code
{
ccall getDefaultDevmodeC "SIS:V:A"
}
printSetup :: !Int !Int !Int !Int !Int !Int !*OSToolbox -> (!OkReturn,!Int,!*OSToolbox)
printSetup _ _ _ _ _ _ _
= code
{
ccall printSetup "IIIIII:VII:I"
}
get_printSetup_with_PRINTDLG :: !Int !*OSToolbox -> (!(!String, !String, !String, !String), !*OSToolbox)
get_printSetup_with_PRINTDLG _ _
= code
{
ccall get_printSetup_with_PRINTDLG "I:VSSSS:I"
}
release_memory_handles :: !Int !*OSToolbox -> *OSToolbox
release_memory_handles _ _
= code
{
ccall release_memory_handles "II-I"
}
startPage :: !HDC !*OSToolbox -> (!OkReturn, !*OSToolbox)
startPage _ _
= code
{
ccall startPage "I:I:I"
}
endPage :: !HDC !*OSToolbox -> (!OkReturn, !*OSToolbox)
endPage _ _
= code
{
ccall endPage "I:I:I"
}
startDoc :: !HDC !*OSToolbox -> (!Int, !*OSToolbox)
// err code: >0:no error, <=0: user cancelled file dialog
startDoc _ _
= code
{
ccall startDoc "I:I:I"
}
endDoc :: !HDC !*OSToolbox -> *OSToolbox
endDoc _ _
= code
{
ccall endDoc "I:V:I"
}
wasCanceled :: !*OSToolbox -> (!Bool,!*OSToolbox)
wasCanceled _
= code
{
ccall wasCanceled ":I:I"
}
deleteDC :: !HDC !*OSToolbox -> *OSToolbox
deleteDC _ _
= code
{
ccall deleteDC "I:V:I"
}
getDC :: !Int !Int !Int !Int !Int !Int !Int !Int !*OSToolbox -> (!Int, !Int, !Int, !Int, !Int, !Int, !*OSToolbox)
// getDC doDialog emulateScreen "getDC called directly from CleanThread" devmodeSize
// first element of result is an error code:
// -1:no error, others: non fatal error
getDC _ _ _ _ _ _ _ _ _
= code
{
ccall getDC "IIIIIIII:VIIIIII:I"
}
addSemaphor :: !Int !*OSToolbox -> (!Int,!*OSToolbox)
addSemaphor _ _
= code
{
ccall addSemaphor "I:I:I"
}
os_printsetuptostring :: !PrintSetup -> String
os_printsetuptostring {devmode, device, driver, output}
= toString (size devmode)+++" "+++toString (size device)+++" "+++toString (size driver)+++" "
+++devmode+++device+++driver+++output
os_stringtoprintsetup :: !String -> PrintSetup
os_stringtoprintsetup string
#! chList = [ch \\ ch<-:string]
(sizeChLists, rest) = seqList (repeatn 3 (splitInt [])) chList
sizes = map (toInt o toString) sizeChLists
(devmodeSize, deviceSize, driverSize) = listTo3Tuple sizes
devmode = toString (rest % (0, devmodeSize-1))
driverStartIndex = devmodeSize+deviceSize
device = toString (rest % (devmodeSize, driverStartIndex-1))
outputStartIndex = driverStartIndex+driverSize
driver = toString (rest % (driverStartIndex, outputStartIndex-1))
output = toString (rest % (outputStartIndex, (size string)-1))
| size devmode==devmodeSize && size device==deviceSize
&& size driver==driverSize && size output==(length rest)-outputStartIndex
&& devmodeSize>0 && deviceSize>0 && driverSize>0 && size output>0
= {devmode=devmode, device=device, driver=driver, output=output}
= {devmode="\0", device="\0", driver="\0", output="\0"}
where
splitInt akku []
= (reverse akku, [])
splitInt akku [ch:chs]
| isDigit ch
= splitInt [ch:akku] chs
= (reverse akku, chs)
listTo3Tuple [e1,e2,e3] = (e1,e2,e3)
|