osprint.icl 16.2 KB
Newer Older
1
2
implementation module osprint

Peter Achten's avatar
Peter Achten committed
3
//	Clean Standard Object I/O library, version 1.2
4
5
6

// MW11 was import StdEnv,intrface,clCrossCall_12, iostate, scheduler
import StdEnv,clCCall_12,clCrossCall_12, iostate, scheduler
7
import ospicture, osevent/*, StdPicture*/, StdWindow, StdPSt
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

::	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_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)

os_printsetupdialog		::	!Bool !PrintSetup !*env
						->	(!PrintSetup, !*env)
os_printsetupdialog isWorld {devmode,device,driver,output} env
	# (os, env)		= EnvGetOS env
	# (devmodePtr,os) = WinMakeCString devmode os
	  (devicePtr,os) = WinMakeCString device os
	  (driverPtr,os) = WinMakeCString driver os
	  (outputPtr,os) = WinMakeCString output os
	  (ok, pdPtr, os)
	  		= CCPrintSetupDialog isWorld (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
		= ({devmode="\0",device="\0",driver="\0",output="\0"}, EnvSetOS os env)
	# (ndevmode,ndevice,ndriver,noutput,os)	= get_printSetup_with_PRINTDLG pdPtr os
	= ({devmode=ndevmode,device=ndevice,driver=ndriver,output=noutput}, EnvSetOS os env)

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"
		}
Peter Achten's avatar
Peter Achten committed
76
77

class PrintEnvironments printEnv
78
79
80
81
82
83
84
85
86
  where
	// MW11 changed Point into Point2
	os_printpageperpage ::	!.Bool !Bool 
							!.x
							.(.x -> .(PrintInfo -> .(*Picture -> ((.Bool,Point2),(.state,*Picture)))))
							((.state,*Picture) -> ((.Bool,Point2),(.state,*Picture)))
							!PrintSetup !*printEnv
						-> 	(Alternative .x .state,!*printEnv)

Peter Achten's avatar
Peter Achten committed
87

88
instance PrintEnvironments (PSt .l)
Peter Achten's avatar
Peter Achten committed
89
where
90
91
92
93
94
95
96
97
98
	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)
Peter Achten's avatar
Peter Achten committed
99
100
101
102
	  where
	  	accFun context
			# (os, context) = EnvGetOS context
	  		# (x,mb_context,os) = printPagePerPageBothSemaphor
103
								doDialog emulateScreen x initFun transFun printSetup (Just context) os
Peter Achten's avatar
Peter Achten committed
104
			= (x,EnvSetOS os (fromJust mb_context))
105
		zipWithSelectState :: .Id *(IOSt .a) -> *(.(Maybe SelectState,Id),*IOSt .a)
106
107
108
109
110
111
		zipWithSelectState id io
			#!	(mbSelectState, io)	= getWindowSelectState id io
			= ((mbSelectState, id), io)
		isEnabled (Just Able)	= True
		isEnabled _				= False

Peter Achten's avatar
Peter Achten committed
112
113
114

instance PrintEnvironments Files
where
115
	os_printpageperpage doDialog emulateScreen x initFun transFun printSetup files
Peter Achten's avatar
Peter Achten committed
116
117
		# (os, files) = EnvGetOS files
		  (x,_,os) = printPagePerPageBothSemaphor
118
		  					doDialog emulateScreen x initFun transFun printSetup Nothing os
Peter Achten's avatar
Peter Achten committed
119
120
		= (x, EnvSetOS os files) 

121
122
123
124
125
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
Peter Achten's avatar
Peter Achten committed
126
127
128
129
130
131
132
// 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)
133
	# (result,mb_context,os) = printPagePerPageBoth p1 p2 x p4 p5 printSetup mb_context os
Peter Achten's avatar
Peter Achten committed
134
135
136
	  (_,os) = addSemaphor (-1) os
	= (result,mb_context,os)

137
138
139
140
141
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
Peter Achten's avatar
Peter Achten committed
142
143
144
	  // do the print dialog (or not) and get the hdc and the printInfo

	  # (err, hdc, printInfo, mb_context, os) 
145
	  		= getPrintInfo doDialog emulateScreen printSetup mb_context os
Peter Achten's avatar
Peter Achten committed
146

147
148
149
150
	  | 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
			
Peter Achten's avatar
Peter Achten committed
151
152
153
154
155
156
157
158
	  // 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
  
159
	  | err <= 0 = (Cancelled x, mb_context, deleteDC hdc os)
Peter Achten's avatar
Peter Achten committed
160
161
162
163
164
165
			// 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
166
// MW11 was 	    (_,_,hdc,os) = unpackPicture picture
Peter Achten's avatar
Peter Achten committed
167
168
169
170
171
172
173
174
175
176
 	    (_,_,_,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
177
178
179
180
181
182
183
	  = (StartedPrinting finalState, mb_context, (deleteDC hdc os))


printPages :: Int 
			((.a,.Picture) -> *((.Bool,u:Origin),*(.a,*Picture)))
			(Bool,v:Origin) .a HDC *(Maybe *Context) !*OSToolbox
		-> *(.a,HDC,*Maybe *Context,!.OSToolbox), [u <= v];
Peter Achten's avatar
Peter Achten committed
184
185
186
187
188
189
190
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
  
191
192
  #	(ok, os)	= startPage hdc os
  | ok == 0 = abort "\nPrint08: Failed in \"StartPage\". Probably not enough memory."
Peter Achten's avatar
Peter Achten committed
193
194
195
196
  #	picture = initPicture origin (hdc,os)
  // apply drawfunctions contained in this page
	((endOfDoc,nextOrigin),(state`,picture))	= fun (state,picture)
  // finish drawing
197
// MW11 was  # (_,_,hdc,os)	= unpackPicture picture
Peter Achten's avatar
Peter Achten committed
198
  # (_,_,_,hdc,os)	= unpackPicture picture
199
   	(ok, os)	= endPage hdc os
Peter Achten's avatar
Peter Achten committed
200
201
202
203
204
205
206
207
208
209
210
    // (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  		

///////////////////////////////////////////////////////////////////////////////

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
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))
		= continuation err data mb_context (get_printSetup_with_PRINTDLG pdPtr 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
   		   )
Peter Achten's avatar
Peter Achten committed
243
244
245
246
247

handleContextOSEvent` :: !OSEvent !Context !*OSToolbox -> (!CrossCallInfo,!Context,!*OSToolbox)
handleContextOSEvent` osEvent context tb
	# (return,context) = handleContextOSEvent osEvent context
	= (setReplyInOSEvent return,context,tb)
248
249
250
251
252
253
254
255
256
257
258
259
260
261
// MW11 was	= (replytocrosscallinfo 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,
Peter Achten's avatar
Peter Achten committed
262
263
264
		Just context,os
	  )

265
266
267
268
269
270
271
272
273
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.p1, rcci.p2, os)

CCstartDoc :: !.HDC !*(Maybe *Context) !*OSToolbox -> *(!Int,!*Maybe *Context,!*OSToolbox)
Peter Achten's avatar
Peter Achten committed
274
275
// error code: -1:no error, 0: user canceled file dialog, others: other error
CCstartDoc hdc Nothing os
276
	# (err,os) = startDoc hdc os
Peter Achten's avatar
Peter Achten committed
277
278
279
280
281
282
	= (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)

283
CCendDoc :: !.HDC !*(Maybe *Context) !*OSToolbox -> *(!*Maybe *Context,!*OSToolbox)
Peter Achten's avatar
Peter Achten committed
284
CCendDoc hdc Nothing os
285
	# os = endDoc hdc os
Peter Achten's avatar
Peter Achten committed
286
287
288
289
290
291
292
293
294
295
296
	= (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
297
298
	# messageText = if (pageNr==0)	""
									(nrStr+++" page"+++(if (pageNr==1) "" "s")+++" printed")
Peter Achten's avatar
Peter Achten committed
299
300
301
302
303
304
305
306
	# (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
307
// MW11 was = packPicture origin defaultPen (fst intPict) (snd intPict)
Peter Achten's avatar
Peter Achten committed
308
309
310
 = packPicture origin defaultPen False (fst intPict) (snd intPict)
	

311
EnvGetOS :: !*env -> (!*OSToolbox,!*env)
Peter Achten's avatar
Peter Achten committed
312
313
314
EnvGetOS env
  = (42,env)

315
EnvSetOS :: !*OSToolbox !*env -> *env
Peter Achten's avatar
Peter Achten committed
316
317
318
319
320
321
322
323
324
325
326
327
EnvSetOS os env
  = env


//////////////////////////////////////////////////
//												//
//				C CALLING FUNCTIONS				//	
//												//
//////////////////////////////////////////////////

:: OkReturn :== Int		// okReturn<>0 <=> ok !

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
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"
		}
Peter Achten's avatar
Peter Achten committed
356

357
358
359
360
361
362
363
364
365
get_printSetup_with_PRINTDLG	::	!Int !*OSToolbox -> (!String, !String, !String, !String, !*OSToolbox)
get_printSetup_with_PRINTDLG _ _
	= code
		{
			ccall get_printSetup_with_PRINTDLG "I:VSSSS:I"
		}

startPage :: !HDC !*OSToolbox -> (!OkReturn, !*OSToolbox)
startPage _ _
Peter Achten's avatar
Peter Achten committed
366
367
	= code
	{
368
			ccall startPage "I:I:I"
Peter Achten's avatar
Peter Achten committed
369
370
	}

371
372
endPage ::	!HDC !*OSToolbox -> (!OkReturn, !*OSToolbox)
endPage _ _
Peter Achten's avatar
Peter Achten committed
373
374
	= code
	{
375
			ccall endPage "I:I:I"
Peter Achten's avatar
Peter Achten committed
376
377
	}

378
startDoc :: !HDC !*OSToolbox -> (!Int, !*OSToolbox)
Peter Achten's avatar
Peter Achten committed
379
			// err code: >0:no error, <=0: user cancelled file dialog
380
startDoc _ _
Peter Achten's avatar
Peter Achten committed
381
382
	= code
	{
383
			ccall startDoc "I:I:I"
Peter Achten's avatar
Peter Achten committed
384
385
	}

386
387
endDoc :: !HDC !*OSToolbox -> *OSToolbox
endDoc _ _
Peter Achten's avatar
Peter Achten committed
388
389
	= code
	{
390
			ccall endDoc "I:V:I"
Peter Achten's avatar
Peter Achten committed
391
392
	}

393
wasCanceled :: !*OSToolbox -> (!Bool,!*OSToolbox)
Peter Achten's avatar
Peter Achten committed
394
395
396
397
398
399
wasCanceled _
	= code
	{
			ccall wasCanceled ":I:I"
	}

400
401
deleteDC :: !HDC !*OSToolbox -> *OSToolbox
deleteDC _ _
Peter Achten's avatar
Peter Achten committed
402
403
	= code
	{
404
			ccall deleteDC "I:V:I"
Peter Achten's avatar
Peter Achten committed
405
406
	}

407
408
409

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
Peter Achten's avatar
Peter Achten committed
410
411
// first element of result is an error code:
// -1:no error, others: non fatal error
412
getDC _ _ _ _ _ _ _ _ _
Peter Achten's avatar
Peter Achten committed
413
414
	= code
	{
415
			ccall getDC "IIIIIIII:VIIIIII:I"
Peter Achten's avatar
Peter Achten committed
416
417
	}

418
addSemaphor :: !Int !*OSToolbox  -> (!Int,!*OSToolbox)
Peter Achten's avatar
Peter Achten committed
419
420
421
422
423
424
addSemaphor _ _
	= code
	{
			ccall addSemaphor "I:I:I"
	}

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
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)