xref: /openbsd-src/gnu/usr.bin/perl/os2/OS2/OS2-Process/Process.pm (revision b39c515898423c8d899e35282f4b395f7cad3298)
1*b39c5158Smillertpackage OS2::localMorphPM;
2*b39c5158Smillert# use strict;
3*b39c5158Smillert
4*b39c5158Smillertsub new {
5*b39c5158Smillert  my ($c,$f) = @_;
6*b39c5158Smillert  OS2::MorphPM($f);
7*b39c5158Smillert  # print STDERR ">>>>>\n";
8*b39c5158Smillert  bless [$f], $c
9*b39c5158Smillert}
10*b39c5158Smillertsub DESTROY {
11*b39c5158Smillert  # print STDERR "<<<<<\n";
12*b39c5158Smillert  OS2::UnMorphPM(shift->[0])
13*b39c5158Smillert}
14*b39c5158Smillert
15*b39c5158Smillertpackage OS2::Process;
16*b39c5158Smillert
17*b39c5158SmillertBEGIN {
18*b39c5158Smillert  require Exporter;
19*b39c5158Smillert  require XSLoader;
20*b39c5158Smillert  #require AutoLoader;
21*b39c5158Smillert
22*b39c5158Smillert  our @ISA = qw(Exporter);
23*b39c5158Smillert  our $VERSION = "1.04";
24*b39c5158Smillert  XSLoader::load('OS2::Process', $VERSION);
25*b39c5158Smillert}
26*b39c5158Smillert
27*b39c5158Smillert# Items to export into callers namespace by default. Note: do not export
28*b39c5158Smillert# names by default without a very good reason. Use EXPORT_OK instead.
29*b39c5158Smillert# Do not simply export all your public functions/methods/constants.
30*b39c5158Smillertour @EXPORT = qw(
31*b39c5158Smillert	P_BACKGROUND
32*b39c5158Smillert	P_DEBUG
33*b39c5158Smillert	P_DEFAULT
34*b39c5158Smillert	P_DETACH
35*b39c5158Smillert	P_FOREGROUND
36*b39c5158Smillert	P_FULLSCREEN
37*b39c5158Smillert	P_MAXIMIZE
38*b39c5158Smillert	P_MINIMIZE
39*b39c5158Smillert	P_NOCLOSE
40*b39c5158Smillert	P_NOSESSION
41*b39c5158Smillert	P_NOWAIT
42*b39c5158Smillert	P_OVERLAY
43*b39c5158Smillert	P_PM
44*b39c5158Smillert	P_QUOTE
45*b39c5158Smillert	P_SESSION
46*b39c5158Smillert	P_TILDE
47*b39c5158Smillert	P_UNRELATED
48*b39c5158Smillert	P_WAIT
49*b39c5158Smillert	P_WINDOWED
50*b39c5158Smillert	my_type
51*b39c5158Smillert	file_type
52*b39c5158Smillert	T_NOTSPEC
53*b39c5158Smillert	T_NOTWINDOWCOMPAT
54*b39c5158Smillert	T_WINDOWCOMPAT
55*b39c5158Smillert	T_WINDOWAPI
56*b39c5158Smillert	T_BOUND
57*b39c5158Smillert	T_DLL
58*b39c5158Smillert	T_DOS
59*b39c5158Smillert	T_PHYSDRV
60*b39c5158Smillert	T_VIRTDRV
61*b39c5158Smillert	T_PROTDLL
62*b39c5158Smillert	T_32BIT
63*b39c5158Smillert
64*b39c5158Smillert	os2constant
65*b39c5158Smillert
66*b39c5158Smillert	ppid
67*b39c5158Smillert	ppidOf
68*b39c5158Smillert	sidOf
69*b39c5158Smillert	scrsize
70*b39c5158Smillert	scrsize_set
71*b39c5158Smillert	kbdChar
72*b39c5158Smillert	kbdhChar
73*b39c5158Smillert	kbdStatus
74*b39c5158Smillert	_kbdStatus_set
75*b39c5158Smillert	kbdhStatus
76*b39c5158Smillert	kbdhStatus_set
77*b39c5158Smillert	vioConfig
78*b39c5158Smillert	viohConfig
79*b39c5158Smillert	vioMode
80*b39c5158Smillert	viohMode
81*b39c5158Smillert	viohMode_set
82*b39c5158Smillert	_vioMode_set
83*b39c5158Smillert	_vioState
84*b39c5158Smillert	_vioState_set
85*b39c5158Smillert	vioFont
86*b39c5158Smillert	vioFont_set
87*b39c5158Smillert	process_entry
88*b39c5158Smillert	process_entries
89*b39c5158Smillert	process_hentry
90*b39c5158Smillert	process_hentries
91*b39c5158Smillert	change_entry
92*b39c5158Smillert	change_entryh
93*b39c5158Smillert	process_hwnd
94*b39c5158Smillert	Title_set
95*b39c5158Smillert	Title
96*b39c5158Smillert	winTitle_set
97*b39c5158Smillert	winTitle
98*b39c5158Smillert	swTitle_set
99*b39c5158Smillert	bothTitle_set
100*b39c5158Smillert	WindowText
101*b39c5158Smillert	WindowText_set
102*b39c5158Smillert	WindowPos
103*b39c5158Smillert	WindowPos_set
104*b39c5158Smillert	hWindowPos
105*b39c5158Smillert	hWindowPos_set
106*b39c5158Smillert	WindowProcess
107*b39c5158Smillert	SwitchToProgram
108*b39c5158Smillert	DesktopWindow
109*b39c5158Smillert	ActiveWindow
110*b39c5158Smillert	ActiveWindow_set
111*b39c5158Smillert	ClassName
112*b39c5158Smillert	FocusWindow
113*b39c5158Smillert	FocusWindow_set
114*b39c5158Smillert	ShowWindow
115*b39c5158Smillert	PostMsg
116*b39c5158Smillert	BeginEnumWindows
117*b39c5158Smillert	EndEnumWindows
118*b39c5158Smillert	GetNextWindow
119*b39c5158Smillert	IsWindow
120*b39c5158Smillert	ChildWindows
121*b39c5158Smillert	out_codepage
122*b39c5158Smillert	out_codepage_set
123*b39c5158Smillert	process_codepage_set
124*b39c5158Smillert	in_codepage
125*b39c5158Smillert	in_codepage_set
126*b39c5158Smillert	cursor
127*b39c5158Smillert	cursor_set
128*b39c5158Smillert	screen
129*b39c5158Smillert	screen_set
130*b39c5158Smillert	process_codepages
131*b39c5158Smillert	QueryWindow
132*b39c5158Smillert	WindowFromId
133*b39c5158Smillert	WindowFromPoint
134*b39c5158Smillert	EnumDlgItem
135*b39c5158Smillert        EnableWindow
136*b39c5158Smillert        EnableWindowUpdate
137*b39c5158Smillert        IsWindowEnabled
138*b39c5158Smillert        IsWindowVisible
139*b39c5158Smillert        IsWindowShowing
140*b39c5158Smillert        WindowPtr
141*b39c5158Smillert        WindowULong
142*b39c5158Smillert        WindowUShort
143*b39c5158Smillert	WindowStyle
144*b39c5158Smillert        SetWindowBits
145*b39c5158Smillert        SetWindowPtr
146*b39c5158Smillert        SetWindowULong
147*b39c5158Smillert        SetWindowUShort
148*b39c5158Smillert        WindowBits_set
149*b39c5158Smillert        WindowPtr_set
150*b39c5158Smillert        WindowULong_set
151*b39c5158Smillert        WindowUShort_set
152*b39c5158Smillert	TopLevel
153*b39c5158Smillert	FocusWindow_set_keep_Zorder
154*b39c5158Smillert
155*b39c5158Smillert	ActiveDesktopPathname
156*b39c5158Smillert	InvalidateRect
157*b39c5158Smillert	CreateFrameControls
158*b39c5158Smillert
159*b39c5158Smillert	ClipbrdFmtInfo
160*b39c5158Smillert	ClipbrdOwner
161*b39c5158Smillert	ClipbrdViewer
162*b39c5158Smillert	ClipbrdData
163*b39c5158Smillert	OpenClipbrd
164*b39c5158Smillert	CloseClipbrd
165*b39c5158Smillert	ClipbrdData_set
166*b39c5158Smillert	ClipbrdOwner_set
167*b39c5158Smillert	ClipbrdViewer_set
168*b39c5158Smillert	EnumClipbrdFmts
169*b39c5158Smillert	EmptyClipbrd
170*b39c5158Smillert	ClipbrdFmtNames
171*b39c5158Smillert	ClipbrdFmtAtoms
172*b39c5158Smillert	AddAtom
173*b39c5158Smillert	FindAtom
174*b39c5158Smillert	DeleteAtom
175*b39c5158Smillert	AtomUsage
176*b39c5158Smillert	AtomName
177*b39c5158Smillert	AtomLength
178*b39c5158Smillert	SystemAtomTable
179*b39c5158Smillert	CreateAtomTable
180*b39c5158Smillert	DestroyAtomTable
181*b39c5158Smillert
182*b39c5158Smillert	_ClipbrdData_set
183*b39c5158Smillert	ClipbrdText
184*b39c5158Smillert	ClipbrdText_set
185*b39c5158Smillert	ClipbrdText_2byte
186*b39c5158Smillert	ClipbrdTextUCS2le
187*b39c5158Smillert	MemoryRegionSize
188*b39c5158Smillert
189*b39c5158Smillert	_MessageBox
190*b39c5158Smillert	MessageBox
191*b39c5158Smillert	_MessageBox2
192*b39c5158Smillert	MessageBox2
193*b39c5158Smillert	get_pointer
194*b39c5158Smillert	LoadPointer
195*b39c5158Smillert	SysPointer
196*b39c5158Smillert	Alarm
197*b39c5158Smillert	FlashWindow
198*b39c5158Smillert
199*b39c5158Smillert	get_title
200*b39c5158Smillert	set_title
201*b39c5158Smillert	io_term
202*b39c5158Smillert);
203*b39c5158Smillertour @EXPORT_OK = qw(
204*b39c5158Smillert	ResetWinError
205*b39c5158Smillert        MPFROMSHORT
206*b39c5158Smillert        MPVOID
207*b39c5158Smillert        MPFROMCHAR
208*b39c5158Smillert        MPFROM2SHORT
209*b39c5158Smillert        MPFROMSH2CH
210*b39c5158Smillert        MPFROMLONG
211*b39c5158Smillert);
212*b39c5158Smillert
213*b39c5158Smillertour $AUTOLOAD;
214*b39c5158Smillert
215*b39c5158Smillertsub AUTOLOAD {
216*b39c5158Smillert    # This AUTOLOAD is used to 'autoload' constants from the constant()
217*b39c5158Smillert    # XS function.  If a constant is not found then control is passed
218*b39c5158Smillert    # to the AUTOLOAD in AutoLoader.
219*b39c5158Smillert
220*b39c5158Smillert    (my $constname = $AUTOLOAD) =~ s/.*:://;
221*b39c5158Smillert    my $val = constant($constname, @_ ? $_[0] : 0);
222*b39c5158Smillert    if ($! != 0) {
223*b39c5158Smillert	if ($! =~ /Invalid/ || $!{EINVAL}) {
224*b39c5158Smillert	    die "Unsupported function $AUTOLOAD"
225*b39c5158Smillert	} else {
226*b39c5158Smillert	    my ($pack,$file,$line) = caller;
227*b39c5158Smillert	    die "Your vendor has not defined OS2::Process macro $constname, used at $file line $line.
228*b39c5158Smillert";
229*b39c5158Smillert	}
230*b39c5158Smillert    }
231*b39c5158Smillert    eval "sub $AUTOLOAD { $val }";
232*b39c5158Smillert    goto &$AUTOLOAD;
233*b39c5158Smillert}
234*b39c5158Smillert
235*b39c5158Smillertsub os2constant {
236*b39c5158Smillert  require OS2::Process::Const;
237*b39c5158Smillert  my $sym = shift;
238*b39c5158Smillert  my ($err, $val) = OS2::Process::Const::constant($sym);
239*b39c5158Smillert  die $err if $err;
240*b39c5158Smillert  $val;
241*b39c5158Smillert}
242*b39c5158Smillert
243*b39c5158Smillertsub const_import {
244*b39c5158Smillert  require OS2::Process::Const;
245*b39c5158Smillert  my $sym = shift;
246*b39c5158Smillert  my $val = os2constant($sym);
247*b39c5158Smillert  my $p = caller(1);
248*b39c5158Smillert
249*b39c5158Smillert  # no strict;
250*b39c5158Smillert
251*b39c5158Smillert  *{"$p\::$sym"} = sub () { $val };
252*b39c5158Smillert  ();			# needed by import()
253*b39c5158Smillert}
254*b39c5158Smillert
255*b39c5158Smillertsub import {
256*b39c5158Smillert  my $class = shift;
257*b39c5158Smillert  my $ini = @_;
258*b39c5158Smillert  @_ = ($class,
259*b39c5158Smillert	map {
260*b39c5158Smillert	  /^(HWND|WM|SC|SWP|WC|PROG|QW|EDI|WS|QWS|QWP|QWL|FF|FI|LS|FS|FCF|BS|MS|TBM|CF|CFI|FID|MB|MBID|CF|CFI|SPTR)_/ ? const_import($_) : $_
261*b39c5158Smillert	} @_);
262*b39c5158Smillert  goto &Exporter::import if @_ > 1 or $ini == 0;
263*b39c5158Smillert}
264*b39c5158Smillert
265*b39c5158Smillert# Preloaded methods go here.
266*b39c5158Smillert
267*b39c5158Smillertsub Title () { (process_entry())[0] }
268*b39c5158Smillert
269*b39c5158Smillert# *Title_set = \&sesmgr_title_set;
270*b39c5158Smillert
271*b39c5158Smillertsub swTitle_set_sw {
272*b39c5158Smillert  my ($title, @sw) = @_;
273*b39c5158Smillert  $sw[0] = $title;
274*b39c5158Smillert  change_entry(@sw);
275*b39c5158Smillert}
276*b39c5158Smillert
277*b39c5158Smillertsub swTitle_set ($) {
278*b39c5158Smillert  my (@sw) = process_entry();
279*b39c5158Smillert  swTitle_set_sw(shift, @sw);
280*b39c5158Smillert}
281*b39c5158Smillert
282*b39c5158Smillertsub winTitle_set_sw {
283*b39c5158Smillert  my ($title, @sw) = @_;
284*b39c5158Smillert  my $h = OS2::localMorphPM->new(0);
285*b39c5158Smillert  WindowText_set $sw[1], $title;
286*b39c5158Smillert}
287*b39c5158Smillert
288*b39c5158Smillertsub winTitle_set ($) {
289*b39c5158Smillert  my (@sw) = process_entry();
290*b39c5158Smillert  winTitle_set_sw(shift, @sw);
291*b39c5158Smillert}
292*b39c5158Smillert
293*b39c5158Smillertsub winTitle () {
294*b39c5158Smillert  my (@sw) = process_entry();
295*b39c5158Smillert  my $h = OS2::localMorphPM->new(0);
296*b39c5158Smillert  WindowText $sw[1];
297*b39c5158Smillert}
298*b39c5158Smillert
299*b39c5158Smillertsub bothTitle_set ($) {
300*b39c5158Smillert  my (@sw) = process_entry();
301*b39c5158Smillert  my $t = shift;
302*b39c5158Smillert  winTitle_set_sw($t, @sw);
303*b39c5158Smillert  swTitle_set_sw($t, @sw);
304*b39c5158Smillert}
305*b39c5158Smillert
306*b39c5158Smillertsub Title_set ($) {
307*b39c5158Smillert  my $t = shift;
308*b39c5158Smillert  return 1 if sesmgr_title_set($t);
309*b39c5158Smillert  return 0 unless $^E == 372;
310*b39c5158Smillert  my (@sw) = process_entry();
311*b39c5158Smillert  winTitle_set_sw($t, @sw);
312*b39c5158Smillert  swTitle_set_sw($t, @sw);
313*b39c5158Smillert}
314*b39c5158Smillert
315*b39c5158Smillertsub process_entry { swentry_expand(process_swentry(@_)) }
316*b39c5158Smillert
317*b39c5158Smillertour @hentry_fields = qw( title owner_hwnd icon_hwnd
318*b39c5158Smillert			 owner_phandle owner_pid owner_sid
319*b39c5158Smillert			 visible nonswitchable jumpable ptype sw_entry );
320*b39c5158Smillert
321*b39c5158Smillertsub swentry_hexpand ($) {
322*b39c5158Smillert  my %h;
323*b39c5158Smillert  @h{@hentry_fields} = swentry_expand(shift);
324*b39c5158Smillert  \%h;
325*b39c5158Smillert}
326*b39c5158Smillert
327*b39c5158Smillertsub process_hentry { swentry_hexpand(process_swentry(@_)) }
328*b39c5158Smillertsub process_hwnd { process_hentry()->{owner_hwnd} }
329*b39c5158Smillert
330*b39c5158Smillertmy $swentry_size = swentry_size();
331*b39c5158Smillert
332*b39c5158Smillertsub sw_entries () {
333*b39c5158Smillert  my $s = swentries_list();
334*b39c5158Smillert  my ($c, $s1) = unpack 'La*', $s;
335*b39c5158Smillert  die "Unconsistent size in swentries_list()" unless 4+$c*$swentry_size == length $s;
336*b39c5158Smillert  my (@l, $e);
337*b39c5158Smillert  push @l, $e while $e = substr $s1, 0, $swentry_size, '';
338*b39c5158Smillert  @l;
339*b39c5158Smillert}
340*b39c5158Smillert
341*b39c5158Smillertsub process_entries () {
342*b39c5158Smillert  map [swentry_expand($_)], sw_entries;
343*b39c5158Smillert}
344*b39c5158Smillert
345*b39c5158Smillertsub process_hentries () {
346*b39c5158Smillert  map swentry_hexpand($_), sw_entries;
347*b39c5158Smillert}
348*b39c5158Smillert
349*b39c5158Smillertsub change_entry {
350*b39c5158Smillert  change_swentry(create_swentry(@_));
351*b39c5158Smillert}
352*b39c5158Smillert
353*b39c5158Smillertsub create_swentryh ($) {
354*b39c5158Smillert  my $h = shift;
355*b39c5158Smillert  create_swentry(@$h{@hentry_fields});
356*b39c5158Smillert}
357*b39c5158Smillert
358*b39c5158Smillertsub change_entryh ($) {
359*b39c5158Smillert  change_swentry(create_swentryh(shift));
360*b39c5158Smillert}
361*b39c5158Smillert
362*b39c5158Smillert# Massage entries into the same order as WindowPos_set:
363*b39c5158Smillertsub WindowPos ($) {
364*b39c5158Smillert  my ($fl, $h, $w, $y, $x, $behind, $hwnd, @rest)
365*b39c5158Smillert	= unpack 'L l4 L4', WindowSWP(shift);
366*b39c5158Smillert  ($x, $y, $fl, $w, $h, $behind, @rest);
367*b39c5158Smillert}
368*b39c5158Smillert
369*b39c5158Smillert# Put them into a hash
370*b39c5158Smillertsub hWindowPos ($) {
371*b39c5158Smillert  my %h;
372*b39c5158Smillert  @h{ qw(flags height width y x behind hwnd reserved1 reserved2) }
373*b39c5158Smillert	= unpack 'L l4 L4', WindowSWP(shift);
374*b39c5158Smillert  \%h;
375*b39c5158Smillert}
376*b39c5158Smillert
377*b39c5158Smillertmy @SWP_keys = ( [qw(width height)],	# SWP_SIZE=1
378*b39c5158Smillert		 [qw(x y)],		# SWP_MOVE=2
379*b39c5158Smillert		 [qw(behind)] );	# SWP_ZORDER=3
380*b39c5158Smillertmy %SWP_def;
381*b39c5158Smillert@SWP_def{ map @$_, @SWP_keys }  = (0) x 20;
382*b39c5158Smillert
383*b39c5158Smillert# Get them from a hash
384*b39c5158Smillertsub hWindowPos_set ($$) {
385*b39c5158Smillert  my $hash = shift;
386*b39c5158Smillert  my $hwnd = (@_ ? shift : $hash->{hwnd} );
387*b39c5158Smillert  my $flags;
388*b39c5158Smillert  if (exists $hash->{flags}) {
389*b39c5158Smillert    $flags = $hash->{flags};
390*b39c5158Smillert  } else {			# Set flags according to existing keys in $hash
391*b39c5158Smillert    $flags = 0;
392*b39c5158Smillert    for my $bit (0..2) {
393*b39c5158Smillert      exists $hash->{$_} and $flags |= (1<<$bit) for @{$SWP_keys[$bit]};
394*b39c5158Smillert    }
395*b39c5158Smillert  }
396*b39c5158Smillert  for my $bit (0..2) {		# Check for required keys
397*b39c5158Smillert    next unless $flags & (1<<$bit);
398*b39c5158Smillert    exists $hash->{$_}
399*b39c5158Smillert      or die sprintf "key $_ required for flags=%#x", $flags
400*b39c5158Smillert	for @{$SWP_keys[$bit]};
401*b39c5158Smillert  }
402*b39c5158Smillert  my %h = (%SWP_def, flags => $flags, %$hash);		# Avoid warnings
403*b39c5158Smillert  my ($x, $y, $fl, $w, $h, $behind) = @h{ qw(x y flags width height behind) };
404*b39c5158Smillert  WindowPos_set($hwnd, $x, $y, $fl, $w, $h, $behind);
405*b39c5158Smillert}
406*b39c5158Smillert
407*b39c5158Smillertsub ChildWindows (;$) {
408*b39c5158Smillert  my $hm = OS2::localMorphPM->new(0);
409*b39c5158Smillert  my @kids;
410*b39c5158Smillert  my $h = BeginEnumWindows(@_ ? shift : 1);	# HWND_DESKTOP
411*b39c5158Smillert  my $w;
412*b39c5158Smillert  push @kids, $w while $w = GetNextWindow $h;
413*b39c5158Smillert  EndEnumWindows $h;
414*b39c5158Smillert  @kids;
415*b39c5158Smillert}
416*b39c5158Smillert
417*b39c5158Smillertsub TopLevel ($) {
418*b39c5158Smillert  my $d = DesktopWindow;
419*b39c5158Smillert  my $w = shift;
420*b39c5158Smillert  while (1) {
421*b39c5158Smillert    my $p = QueryWindow $w, 5;	# QW_PARENT;
422*b39c5158Smillert    return $w if not $p or $p == $d;
423*b39c5158Smillert    $w = $p;
424*b39c5158Smillert  }
425*b39c5158Smillert}
426*b39c5158Smillert
427*b39c5158Smillertsub FocusWindow_set_keep_Zorder ($) {
428*b39c5158Smillert  my $w = shift;
429*b39c5158Smillert  my $t = TopLevel $w;
430*b39c5158Smillert  my $b = hWindowPos($t)->{behind}; # we are behind this
431*b39c5158Smillert  EnableWindowUpdate($t, 0);
432*b39c5158Smillert  FocusWindow_set($w);
433*b39c5158Smillert# sleep 1;    # Make flicker stronger when present
434*b39c5158Smillert  hWindowPos_set {behind => $b}, $t;
435*b39c5158Smillert  EnableWindowUpdate($t, 1);
436*b39c5158Smillert}
437*b39c5158Smillert
438*b39c5158Smillertsub WindowStyle ($) {
439*b39c5158Smillert  WindowULong(shift,-2);	# QWL_STYLE
440*b39c5158Smillert}
441*b39c5158Smillert
442*b39c5158Smillertsub OS2::localClipbrd::new {
443*b39c5158Smillert  my ($c) = shift;
444*b39c5158Smillert  my $morph = [];
445*b39c5158Smillert  push @$morph, OS2::localMorphPM->new(0) unless shift;
446*b39c5158Smillert  &OpenClipbrd;
447*b39c5158Smillert  # print STDERR ">>>>>\n";
448*b39c5158Smillert  bless $morph, $c
449*b39c5158Smillert}
450*b39c5158Smillertsub OS2::localClipbrd::DESTROY {
451*b39c5158Smillert  # print STDERR "<<<<<\n";
452*b39c5158Smillert  CloseClipbrd();
453*b39c5158Smillert}
454*b39c5158Smillert
455*b39c5158Smillertsub OS2::localFlashWindow::new ($$) {
456*b39c5158Smillert  my ($c, $w) = (shift, shift);
457*b39c5158Smillert  my $morph = OS2::localMorphPM->new(0);
458*b39c5158Smillert  FlashWindow($w, 1);
459*b39c5158Smillert  # print STDERR ">>>>>\n";
460*b39c5158Smillert  bless [$w, $morph], $c
461*b39c5158Smillert}
462*b39c5158Smillertsub OS2::localFlashWindow::DESTROY {
463*b39c5158Smillert  # print STDERR "<<<<<\n";
464*b39c5158Smillert  FlashWindow(shift->[0], 0);
465*b39c5158Smillert}
466*b39c5158Smillert
467*b39c5158Smillert# Good for \0-terminated text (not "text/unicode" and other Firefox stuff)
468*b39c5158Smillertsub ClipbrdText (@) {
469*b39c5158Smillert  my $h = OS2::localClipbrd->new;
470*b39c5158Smillert  my $data = ClipbrdData @_;
471*b39c5158Smillert  return unless $data;
472*b39c5158Smillert  my $lim = MemoryRegionSize($data);
473*b39c5158Smillert  $lim = StrLen($data, $lim);			# Look for 1-byte 0
474*b39c5158Smillert  return unpack "P$lim", pack 'L', $data;
475*b39c5158Smillert}
476*b39c5158Smillert
477*b39c5158Smillertsub ClipbrdText_2byte (@) {
478*b39c5158Smillert  my $h = OS2::localClipbrd->new;
479*b39c5158Smillert  my $data = ClipbrdData @_;
480*b39c5158Smillert  return unless $data;
481*b39c5158Smillert  my $lim = MemoryRegionSize($data);
482*b39c5158Smillert  $lim = StrLen($data, $lim, 2);		# Look for 2-byte 0
483*b39c5158Smillert  return unpack "P$lim", pack 'L', $data;
484*b39c5158Smillert}
485*b39c5158Smillert
486*b39c5158Smillertsub ClipbrdTextUCS2le (@) {
487*b39c5158Smillert  my $txt = ClipbrdText_2byte @_;		# little-endian shorts
488*b39c5158Smillert  #require Unicode::String;
489*b39c5158Smillert  pack "U*", unpack "v*", $txt;
490*b39c5158Smillert}
491*b39c5158Smillert
492*b39c5158Smillertsub ClipbrdText_set ($;@) {
493*b39c5158Smillert  my $h = OS2::localClipbrd->new;
494*b39c5158Smillert  EmptyClipbrd();				# It may contain other types
495*b39c5158Smillert  my ($txt, $no_convert_nl) = (shift, shift);
496*b39c5158Smillert  ClipbrdData_set($txt, !$no_convert_nl, @_);
497*b39c5158Smillert}
498*b39c5158Smillert
499*b39c5158Smillertsub ClipbrdFmtAtoms {
500*b39c5158Smillert  my $h = OS2::localClipbrd->new('nomorph');
501*b39c5158Smillert  my $fmt = 0;
502*b39c5158Smillert  my @formats;
503*b39c5158Smillert  push @formats, $fmt while eval {$fmt = EnumClipbrdFmts $fmt};
504*b39c5158Smillert  die $@ if $@ and $^E == 0x1001 and $fmt = 0;	# Croaks on empty list?
505*b39c5158Smillert  @formats;
506*b39c5158Smillert}
507*b39c5158Smillert
508*b39c5158Smillertsub ClipbrdFmtNames {
509*b39c5158Smillert  map AtomName($_), ClipbrdFmtAtoms(@_);
510*b39c5158Smillert}
511*b39c5158Smillert
512*b39c5158Smillertsub MessageBox ($;$$$$$) {
513*b39c5158Smillert  my $morph = OS2::localMorphPM->new(0);
514*b39c5158Smillert  die "MessageBox needs text" unless @_;
515*b39c5158Smillert  push @_ , ($0 eq '-e' ? "Perl one-liner's message" : "$0 message") if @_ == 1;
516*b39c5158Smillert  &_MessageBox;
517*b39c5158Smillert}
518*b39c5158Smillert
519*b39c5158Smillertmy %pointers;
520*b39c5158Smillert
521*b39c5158Smillertsub get_pointer ($;$$) {
522*b39c5158Smillert  my $id = $_[0];
523*b39c5158Smillert  return $pointers{$id} if exists $pointers{$id};
524*b39c5158Smillert  $pointers{$id} = &SysPointer;
525*b39c5158Smillert}
526*b39c5158Smillert
527*b39c5158Smillert# $button needs to be of the form 'String', ['String'] or ['String', flag].
528*b39c5158Smillert# If ['String'], it is assumed the default button; same for 'String' if $only
529*b39c5158Smillert# is set.
530*b39c5158Smillertsub process_MB2 ($$;$) {
531*b39c5158Smillert  die "process_MB2() needs 2 arguments, got '@_'" unless @_ == 2 or @_ == 3;
532*b39c5158Smillert  my ($button, $ret, $only) = @_;
533*b39c5158Smillert  # default is BS_PUSHBUTTON, add BS_DEFAULT if $only is set
534*b39c5158Smillert  $button = [$button, $only ? 0x400 : 0] unless ref $button eq 'ARRAY';
535*b39c5158Smillert  push @$button, 0x400 if @$button == 1; # BS_PUSHBUTTON|BS_DEFAULT
536*b39c5158Smillert  die "Button needs to be of the form 'String', ['String'] or ['String', flag]"
537*b39c5158Smillert    unless @$button == 2;
538*b39c5158Smillert  pack "Z71 x L l", $button->[0], $ret, $button->[1]; # name, retval, flag
539*b39c5158Smillert}
540*b39c5158Smillert
541*b39c5158Smillert# If one button, make it the default one even if it is of 'String' => val form.
542*b39c5158Smillert# If icon is of the form 'SP#<number>', load this via SysPointer.
543*b39c5158Smillertsub process_MB2_INFO ($;$$$) {
544*b39c5158Smillert  my $l = 0;
545*b39c5158Smillert  my $out;
546*b39c5158Smillert  die "process_MB2_INFO() needs 1..4 arguments" unless @_ and @_ < 5;
547*b39c5158Smillert  my $buttons = shift;
548*b39c5158Smillert  die "Buttons array should consist of pairs" if @$buttons % 2;
549*b39c5158Smillert
550*b39c5158Smillert  push @_, 0 unless @_;		# Icon id; non-0 ignored without MB_CUSTOMICON
551*b39c5158Smillert  # Box flags (MB_MOVABLE and MB_INFORMATION or MB_CUSTOMICON)
552*b39c5158Smillert  push @_, ($_[0] ? 0x4080 : 0x4030) unless @_ > 1;
553*b39c5158Smillert  push @_, 0 unless @_ > 2;	# Notify window
554*b39c5158Smillert
555*b39c5158Smillert  my ($icon, $style, $notify) = (shift, shift, shift);
556*b39c5158Smillert  $icon = get_pointer $1 if $icon =~ /^SP#(\d+)\z/;
557*b39c5158Smillert  $out = pack "L L L L",	# icon, #buttons, style, notify, buttons
558*b39c5158Smillert      $icon, @$buttons/2, $style, $notify;
559*b39c5158Smillert  $out .= join '',
560*b39c5158Smillert    map process_MB2($buttons->[2*$_], $buttons->[2*$_+1], @$buttons == 2),
561*b39c5158Smillert      0..@$buttons/2-1;
562*b39c5158Smillert  pack('L', length(pack 'L', 0) + length $out) . $out;
563*b39c5158Smillert}
564*b39c5158Smillert
565*b39c5158Smillert# MessageBox2 'Try this', OS2::Process::process_MB2_INFO([['Dismiss', 0] => 0x1000], OS2::Process::get_pointer(22),0x4080,0), 'me', 1, 0, 0
566*b39c5158Smillert# or the shortcut
567*b39c5158Smillert# MessageBox2 'Try this', [[['Dismiss', 0] => 0x1000], 'SP#22'], 'me'
568*b39c5158Smillert# 0x80 means MB_CUSTOMICON (does not focus?!).  This focuses:
569*b39c5158Smillert# MessageBox2 'Try this', [[['Dismiss',0x400] => 0x1000], 0, 0x4030,0]
570*b39c5158Smillert# 0x400 means BS_DEFAULT.  This is the same as the shortcut
571*b39c5158Smillert# MessageBox2 'Try this', [[Dismiss => 0x1000]]
572*b39c5158Smillertsub MessageBox2 ($;$$$$$) {
573*b39c5158Smillert  my $morph = OS2::localMorphPM->new(0);
574*b39c5158Smillert  die "MessageBox needs text" unless @_;
575*b39c5158Smillert  push @_ , [[Dismiss => 0x1000], # Name, retval (style BS_PUSHBUTTON|BS_DEFAULT)
576*b39c5158Smillert	     #0,		# e.g., get_pointer(11),# SPTR_ICONINFORMATION
577*b39c5158Smillert	     #0x4030,		# = MB_MOVEABLE | MB_INFORMATION
578*b39c5158Smillert	     #0,		# Notify window; was 1==HWND_DESKTOP
579*b39c5158Smillert	    ] if @_ == 1;
580*b39c5158Smillert  push @_ , ($0 eq '-e' ? "Perl one-liner" : $0). "'s message" if @_ == 2;
581*b39c5158Smillert  $_[1] = &process_MB2_INFO(@{$_[1]}) if ref($_[1]) eq 'ARRAY';
582*b39c5158Smillert  &_MessageBox2;
583*b39c5158Smillert}
584*b39c5158Smillert
585*b39c5158Smillertmy %mbH_default = (
586*b39c5158Smillert  text => 'Something happened',
587*b39c5158Smillert  title => ($0 eq '-e' ? "Perl one-liner" : $0). "'s message",
588*b39c5158Smillert  parent => 1,			# HWND_DESKTOP
589*b39c5158Smillert  owner => 0,
590*b39c5158Smillert  helpID => 0,
591*b39c5158Smillert  buttons => ['Dismiss' => 0x1000],
592*b39c5158Smillert  default_button => 1,
593*b39c5158Smillert#  icon => 0x30,		# MB_INFORMATION
594*b39c5158Smillert#  iconID => 0,			# XXX???
595*b39c5158Smillert  flags => 0,			# XXX???
596*b39c5158Smillert  notifyWindow => 0,		# XXX???
597*b39c5158Smillert);
598*b39c5158Smillert
599*b39c5158Smillertsub MessageBoxH {
600*b39c5158Smillert  die "MessageBoxH: even number of arguments expected" if @_ % 2;
601*b39c5158Smillert  my %a = (%mbH_default, @_);
602*b39c5158Smillert  die "MessageBoxH: even number of elts of button array expected"
603*b39c5158Smillert    if @{$a{buttons}} % 2;
604*b39c5158Smillert  if (defined $a{iconID}) {
605*b39c5158Smillert    $a{flags} |= 0x80;		# MB_CUSTOMICON
606*b39c5158Smillert  } else {
607*b39c5158Smillert    $a{icon} = 0x30 unless defined $a{icon};
608*b39c5158Smillert    $a{iconID} = 0;
609*b39c5158Smillert    $a{flags} |= $a{icon};
610*b39c5158Smillert  }
611*b39c5158Smillert  # Mark default_button as MessageBox2() expects it:
612*b39c5158Smillert  $a{buttons}[2*$a{default_button}] = [$a{buttons}[2*$a{default_button}]];
613*b39c5158Smillert
614*b39c5158Smillert  my $use_2 = 'ARRAY' eq ref $a{buttons};
615*b39c5158Smillert  return
616*b39c5158Smillert    MessageBox2 $a{text}, [@a{qw(buttons iconID flags notifyWindow)}],
617*b39c5158Smillert      $a{parent}, $a{owner}, $a{helpID}
618*b39c5158Smillert	if $use_2;
619*b39c5158Smillert  die "MessageBoxH: unexpected format of argument 'buttons'";
620*b39c5158Smillert}
621*b39c5158Smillert
622*b39c5158Smillert# backward compatibility
623*b39c5158Smillert*set_title = \&Title_set;
624*b39c5158Smillert*get_title = \&Title;
625*b39c5158Smillert
626*b39c5158Smillert# New (logical) names
627*b39c5158Smillert*WindowBits_set = \&SetWindowBits;
628*b39c5158Smillert*WindowPtr_set = \&SetWindowPtr;
629*b39c5158Smillert*WindowULong_set = \&SetWindowULong;
630*b39c5158Smillert*WindowUShort_set = \&SetWindowUShort;
631*b39c5158Smillert
632*b39c5158Smillert# adapter; display; cbMemory; Configuration; VDHVersion; Flags; HWBufferSize;
633*b39c5158Smillert# FullSaveSize; PartSaveSize; EMAdaptersOFF; EMDisplaysOFF;
634*b39c5158Smillertsub vioConfig (;$$) {
635*b39c5158Smillert  my $data = &_vioConfig;
636*b39c5158Smillert  my @out = unpack 'x[S]SSLSSSLLLSS', $data;
637*b39c5158Smillert  # If present, offset points to S/S (with only the first work making sense)
638*b39c5158Smillert  my (@adaptersEMU, @displayEMU);
639*b39c5158Smillert  @displaysEMU = unpack("x[$out[10]]S/S", $data), pop @out if @out > 10;
640*b39c5158Smillert  @adaptersEMU = unpack("x[$out[ 9]]S/S", $data), pop @out if @out > 9;
641*b39c5158Smillert  $out[9] = $adaptersEMU[0] if @adaptersEMU;
642*b39c5158Smillert  $out[10] = $displaysEMU[0] if @displaysEMU;
643*b39c5158Smillert  @out;
644*b39c5158Smillert}
645*b39c5158Smillert
646*b39c5158Smillertmy @vioConfig = qw(adapter display cbMemory Configuration VDHVersion Flags
647*b39c5158Smillert		   HWBufferSize FullSaveSize PartSaveSize EMAdapters EMDisplays);
648*b39c5158Smillert
649*b39c5158Smillertsub viohConfig (;$$) {
650*b39c5158Smillert  my %h;
651*b39c5158Smillert  @h{@vioConfig} = &vioConfig;
652*b39c5158Smillert  %h;
653*b39c5158Smillert}
654*b39c5158Smillert
655*b39c5158Smillert# fbType; color; col; row; hres; vres; fmt_ID; attrib; buf_addr; buf_length;
656*b39c5158Smillert# full_length; partial_length; ext_data_addr;
657*b39c5158Smillertsub vioMode() {unpack 'x[S]CCSSSSCCLLLLL', _vioMode}
658*b39c5158Smillert
659*b39c5158Smillertmy @vioMode = qw( fbType color col row hres vres fmt_ID attrib buf_addr
660*b39c5158Smillert		  buf_length full_length partial_length ext_data_addr);
661*b39c5158Smillert
662*b39c5158Smillertsub viohMode() {
663*b39c5158Smillert  my %h;
664*b39c5158Smillert  @h{@vioMode} = vioMode;
665*b39c5158Smillert  %h;
666*b39c5158Smillert}
667*b39c5158Smillert
668*b39c5158Smillertsub viohMode_set {
669*b39c5158Smillert  my %h = (viohMode, @_);
670*b39c5158Smillert  my $o = pack 'x[S]CCSSSSCCLLLLL', @h{@vioMode};
671*b39c5158Smillert  $o = pack 'SCCSSSSCCLLLLL', length $o, @h{@vioMode};
672*b39c5158Smillert  _vioMode_set($o);
673*b39c5158Smillert}
674*b39c5158Smillert
675*b39c5158Smillertsub kbdChar (;$$) {unpack 'CCCCSL', &_kbdChar}
676*b39c5158Smillert
677*b39c5158Smillertmy @kbdChar = qw(ascii scancode status nlsstate shifts time);
678*b39c5158Smillertsub kbdhChar (;$$) {
679*b39c5158Smillert  my %h;
680*b39c5158Smillert  @h{@kbdChar} = &kbdChar;
681*b39c5158Smillert  %h
682*b39c5158Smillert}
683*b39c5158Smillert
684*b39c5158Smillertsub kbdStatus (;$) {unpack 'x[S]SSSS', &_kbdStatus}
685*b39c5158Smillertmy @kbdStatus = qw(state turnChar intCharFlags shifts);
686*b39c5158Smillertsub kbdhStatus (;$) {
687*b39c5158Smillert  my %h;
688*b39c5158Smillert  @h{@kbdStatus} = &kbdStatus;
689*b39c5158Smillert  %h
690*b39c5158Smillert}
691*b39c5158Smillertsub kbdhStatus_set {
692*b39c5158Smillert  my $h = (@_ % 2 ? shift @_ : 0);
693*b39c5158Smillert  my %h = (kbdhStatus($h), @_);
694*b39c5158Smillert  my $o = pack 'x[S]SSSS', @h{@kbdStatus};
695*b39c5158Smillert  $o = pack 'SSSSS', length $o, @h{@kbdStatus};
696*b39c5158Smillert  _kbdStatus_set($o,$h);
697*b39c5158Smillert}
698*b39c5158Smillert
699*b39c5158Smillert#sub DeleteAtom		{ !WinDeleteAtom(@_) }
700*b39c5158Smillertsub DeleteAtom		{ !_DeleteAtom(@_) }
701*b39c5158Smillertsub DestroyAtomTable    { !_DestroyAtomTable(@_) }
702*b39c5158Smillert
703*b39c5158Smillert# XXXX This is a wrong order: we start keyreader, then screenwriter; so it is
704*b39c5158Smillert# the writer who gets signals.
705*b39c5158Smillert
706*b39c5158Smillert# XXXX Do we ever get a message "screenwriter killed"???  If reader HUPs us...
707*b39c5158Smillert# Large buffer works at least for read from pipes; should we binmode???
708*b39c5158Smillertsub __term_mirror_screen {   # Read from fd=$in and write to the console
709*b39c5158Smillert  local $SIG{TERM} = $SIG{HUP} = $SIG{BREAK} = $SIG{INT} = # die() can stop END
710*b39c5158Smillert    sub { my $s = shift; warn "screenwriter killed ($s)...\n";};
711*b39c5158Smillert  my $in = shift;
712*b39c5158Smillert  open IN, "<&=$in" or die "open <&=$in: $!";
713*b39c5158Smillert  # Attempt to redirect to STDERR/OUT is not very useful, but try this anyway...
714*b39c5158Smillert  open OUT, '>', '/dev/con' or open OUT, '>&STDERR' or open OUT, '>&STDOUT'
715*b39c5158Smillert	and select OUT or die "Can't open /dev/con or STDERR/STDOUT for write";
716*b39c5158Smillert  $| = 1; local $SIG{TERM} = sub { die "screenwriter exits...\n"};
717*b39c5158Smillert  binmode IN; binmode OUT;
718*b39c5158Smillert  eval { print $_ while sysread IN, $_, 1<<16; };	# print to OUT...
719*b39c5158Smillert  warn $@ if $@;
720*b39c5158Smillert  warn "Screenwriter can't read any more ($!, $^E), terminating...\n";
721*b39c5158Smillert}
722*b39c5158Smillert
723*b39c5158Smillert# Does not automatically ends when the parent exits if related => 0
724*b39c5158Smillert# copy from fd=$in to screen ; same for $out; or $in may be a named pipe
725*b39c5158Smillertsub __term_mirror {
726*b39c5158Smillert  my $pid;
727*b39c5158Smillert  ### If related => 1, we get TERM when our parent exits...
728*b39c5158Smillert  local $SIG{TERM} = sub { my $s = shift;
729*b39c5158Smillert			   die "keyreader exits in a few secs ($s)...\n" };
730*b39c5158Smillert  my ($in, $out) = (shift, shift);
731*b39c5158Smillert  if (defined $out and length $out) {	# Allow '' for ease of @ARGV
732*b39c5158Smillert    open OUT, ">&=$out" or die "Cannot open &=$out for write: $!";
733*b39c5158Smillert    fcntl(OUT, 4, 1);		# F_SETFD, NOINHERIT
734*b39c5158Smillert    open IN, "<&=$in" or die "Cannot open &=$in for read/ioctl: $!";
735*b39c5158Smillert    fcntl(IN,  4, 0);		# F_SETFD, INHERIT
736*b39c5158Smillert  } else {
737*b39c5158Smillert    warn "Unexpected i/o pipe name: `$in'" unless $in =~ m,^[\\/]pipe[\\/],i;
738*b39c5158Smillert    OS2::pipe $in, 'wait';
739*b39c5158Smillert    open OUT, '+<', $in or die "Can't open `$in' for r/w: $!";
740*b39c5158Smillert    fcntl(OUT,  4, 0);		# F_SETFD, INHERIT
741*b39c5158Smillert    $in = fileno OUT;
742*b39c5158Smillert    undef $out;
743*b39c5158Smillert  }
744*b39c5158Smillert  my %opt = @_;
745*b39c5158Smillert  Title_set $opt{title}				if exists $opt{title};
746*b39c5158Smillert  &scrsize_set(split /,/, $opt{scrsize})	if exists $opt{scrsize};
747*b39c5158Smillert
748*b39c5158Smillert  my @i = map +('-I', $_), @INC;	# Propagate @INC
749*b39c5158Smillert
750*b39c5158Smillert  # Careful unless PERL_SIGNALS=unsafe: SIGCHLD does not work...
751*b39c5158Smillert  $SIG{CHLD} = sub {wait; die "Keyreader follows screenwriter...\n"}
752*b39c5158Smillert	unless defined $out;
753*b39c5158Smillert
754*b39c5158Smillert  $pid = system 1, $^X, @i, '-MOS2::Process',
755*b39c5158Smillert	 '-we', 'END {sleep 2} OS2::Process::__term_mirror_screen shift', $in;
756*b39c5158Smillert  close IN if defined $out;
757*b39c5158Smillert  $pid > 0 or die "Cannot start a grandkid";
758*b39c5158Smillert
759*b39c5158Smillert  open STDIN, '</dev/con' or warn "reopen stdin: $!";
760*b39c5158Smillert  select OUT;    $| = 1;  binmode OUT;	# need binmode: sysread() may be bin
761*b39c5158Smillert  $SIG{PIPE} = sub { die "writing to a closed pipe" };
762*b39c5158Smillert  $SIG{HUP} = $SIG{BREAK} = $SIG{INT} = $SIG{TERM};
763*b39c5158Smillert  # Workaround: EMX v61 won't return pid on SESSION|UNRELATED after fork()...
764*b39c5158Smillert  syswrite OUT, pack 'L', $$ or die "syswrite failed: $!" if $opt{writepid};
765*b39c5158Smillert  # Turn Nodelay on kbd.  Pipe is automatically nodelay...
766*b39c5158Smillert  if ($opt{read_by_key}) {
767*b39c5158Smillert    if (eval {require Term::ReadKey; 1}) {
768*b39c5158Smillert      Term::ReadKey::ReadMode(4);
769*b39c5158Smillert    } else { warn "can't load Term::ReadKey; input by lines..." }
770*b39c5158Smillert  }
771*b39c5158Smillert  print while sysread STDIN, $_, 1<<($opt{smallbuffer} ? 0 : 16); # to OUT
772*b39c5158Smillert}
773*b39c5158Smillert
774*b39c5158Smillertmy $c = 0;
775*b39c5158Smillertsub io_term {	# arguments as hash: read_by_key/title/scrsize/related/writepid
776*b39c5158Smillert  # read_by_key disables echo too...
777*b39c5158Smillert  local $\  = '';
778*b39c5158Smillert  my ($sysf, $in1, $out1, $in2, $out2, $f1, $f2, $fd) = 4;	# P_SESSION
779*b39c5158Smillert  my %opt = @_;
780*b39c5158Smillert
781*b39c5158Smillert  if ($opt{related}) {
782*b39c5158Smillert    pipe $in1, $out1 or die "pipe(): $!";
783*b39c5158Smillert    pipe $in2, $out2 or do { close($in1), close($out1), die "pipe(): $!" };
784*b39c5158Smillert    $f1 = fileno $in1; $f2 = fileno $out2;
785*b39c5158Smillert    fcntl($in2, 4, 1); fcntl($out1, 4, 1);		# F_SETFD, NOINHERIT
786*b39c5158Smillert    fcntl($in1, 4, 0); fcntl($out2, 4, 0);		# F_SETFD, INHERIT
787*b39c5158Smillert  } else {
788*b39c5158Smillert    $f1 = "/pipe/perlmodule/OS2/Process/$$-" . $c++;
789*b39c5158Smillert    $out1 = OS2::pipe $f1, 'rw' or die "OS2::pipe(): $^E";
790*b39c5158Smillert    #open $out1, "+<&=$fd" or die "dup($fd): $!, $^E";
791*b39c5158Smillert    fcntl($out1, 4, 1);		# F_SETFD, NOINHERIT
792*b39c5158Smillert    #$in2 = $out1;
793*b39c5158Smillert    $f2 = '';
794*b39c5158Smillert    $sysf |= 0x40000;		# P_UNRELATED
795*b39c5158Smillert    $opt{writepid} = 1, unless exists $opt{writepid};
796*b39c5158Smillert  }
797*b39c5158Smillert
798*b39c5158Smillert  # system P_SESSION will fail if there is another process
799*b39c5158Smillert  # in the same session with a "related" asynchronous child session.
800*b39c5158Smillert  my @i = map +('-I', $_), @INC;	# Propagate @INC
801*b39c5158Smillert  my $krun = <<'EOS';
802*b39c5158Smillert     END {sleep($sleep || 5)}
803*b39c5158Smillert     use OS2::Process; $sleep = 1;
804*b39c5158Smillert     OS2::Process::__term_mirror(@ARGV);
805*b39c5158SmillertEOS
806*b39c5158Smillert  my $kpid;
807*b39c5158Smillert  if ($opt{related}) {
808*b39c5158Smillert    $kpid = system $sysf, $^X, @i, '-we', $krun, $f1, $f2, %opt;
809*b39c5158Smillert  } else {
810*b39c5158Smillert    local $ENV{PERL_SIGNALS} = 'unsafe';
811*b39c5158Smillert    $kpid = system $sysf, $^X, @i, '-we', $krun, $f1, $f2, %opt;
812*b39c5158Smillert  }
813*b39c5158Smillert  close $in1 or warn if defined $in1;
814*b39c5158Smillert  close $out2 or warn if defined $out2;
815*b39c5158Smillert  # EMX BUG with $kpid == 0 after fork()
816*b39c5158Smillert  do { close($in2), ($out1 != $in2 and close($out1)),
817*b39c5158Smillert       die "system $sysf, $^X: kid=$kpid, \$!=`$!', \$^E=`$^E'" }
818*b39c5158Smillert     unless $kpid > 0 or $kpid == 0 and $opt{writepid};
819*b39c5158Smillert  # Can't read or write until the kid opens the pipes
820*b39c5158Smillert  OS2::pipeCntl $out1, 'connect', 'wait' unless length $f2;
821*b39c5158Smillert  # Without duping: write after read (via termio) on the same fd dups input
822*b39c5158Smillert  open $in2, '<&', $out1 or die "dup($out1): $^E" unless $opt{related};
823*b39c5158Smillert  if ($opt{writepid}) {
824*b39c5158Smillert    my $c = length pack 'L', 0;
825*b39c5158Smillert    my $c1 = sysread $in2, (my $pid), $c;
826*b39c5158Smillert    $c1 == $c or die "unexpected length read: $c1 vs $c";
827*b39c5158Smillert    $kpid = unpack 'L', $pid;
828*b39c5158Smillert  }
829*b39c5158Smillert  return ($in2, $out1, $kpid);
830*b39c5158Smillert}
831*b39c5158Smillert
832*b39c5158Smillert# Autoload methods go after __END__, and are processed by the autosplit program.
833*b39c5158Smillert
834*b39c5158Smillert1;
835*b39c5158Smillert__END__
836*b39c5158Smillert
837*b39c5158Smillert=head1 NAME
838*b39c5158Smillert
839*b39c5158SmillertOS2::Process - exports constants for system() call, and process control on OS2.
840*b39c5158Smillert
841*b39c5158Smillert=head1 SYNOPSIS
842*b39c5158Smillert
843*b39c5158Smillert    use OS2::Process;
844*b39c5158Smillert    $pid = system(P_PM | P_BACKGROUND, "epm.exe");
845*b39c5158Smillert
846*b39c5158Smillert=head1 DESCRIPTION
847*b39c5158Smillert
848*b39c5158Smillert=head2 Optional argument to system()
849*b39c5158Smillert
850*b39c5158Smillertthe builtin function system() under OS/2 allows an optional first
851*b39c5158Smillertargument which denotes the mode of the process. Note that this argument is
852*b39c5158Smillertrecognized only if it is strictly numerical.
853*b39c5158Smillert
854*b39c5158SmillertYou can use either one of the process modes:
855*b39c5158Smillert
856*b39c5158Smillert	P_WAIT (0)	= wait until child terminates (default)
857*b39c5158Smillert	P_NOWAIT	= do not wait until child terminates
858*b39c5158Smillert	P_SESSION	= new session
859*b39c5158Smillert	P_DETACH	= detached
860*b39c5158Smillert	P_PM		= PM program
861*b39c5158Smillert
862*b39c5158Smillertand optionally add PM and session option bits:
863*b39c5158Smillert
864*b39c5158Smillert	P_DEFAULT (0)	= default
865*b39c5158Smillert	P_MINIMIZE	= minimized
866*b39c5158Smillert	P_MAXIMIZE	= maximized
867*b39c5158Smillert	P_FULLSCREEN	= fullscreen (session only)
868*b39c5158Smillert	P_WINDOWED	= windowed (session only)
869*b39c5158Smillert
870*b39c5158Smillert	P_FOREGROUND	= foreground (if running in foreground)
871*b39c5158Smillert	P_BACKGROUND	= background
872*b39c5158Smillert
873*b39c5158Smillert	P_NOCLOSE	= don't close window on exit (session only)
874*b39c5158Smillert
875*b39c5158Smillert	P_QUOTE		= quote all arguments
876*b39c5158Smillert	P_TILDE		= MKS argument passing convention
877*b39c5158Smillert	P_UNRELATED	= do not kill child when father terminates
878*b39c5158Smillert
879*b39c5158Smillert=head2 Access to process properties
880*b39c5158Smillert
881*b39c5158SmillertOn OS/2 processes have the usual I<parent/child> semantic;
882*b39c5158Smillertadditionally, there is a hierarchy of sessions with their own
883*b39c5158SmillertI<parent/child> tree.  A session is either a FS session, or a windowed
884*b39c5158Smillertpseudo-session created by PM.  A session is a "unit of user
885*b39c5158Smillertinteraction", a change to in/out settings in one of them does not
886*b39c5158Smillertaffect other sessions.
887*b39c5158Smillert
888*b39c5158Smillert=over
889*b39c5158Smillert
890*b39c5158Smillert=item my_type()
891*b39c5158Smillert
892*b39c5158Smillertreturns the type of the current process (one of
893*b39c5158Smillert"FS", "DOS", "VIO", "PM", "DETACH" and "UNKNOWN"), or C<undef> on error.
894*b39c5158Smillert
895*b39c5158Smillert=item C<file_type(file)>
896*b39c5158Smillert
897*b39c5158Smillertreturns the type of the executable file C<file>, or
898*b39c5158Smillertdies on error.  The bits 0-2 of the result contain one of the values
899*b39c5158Smillert
900*b39c5158Smillert=over
901*b39c5158Smillert
902*b39c5158Smillert=item C<T_NOTSPEC> (0)
903*b39c5158Smillert
904*b39c5158SmillertApplication type is not specified in the executable header.
905*b39c5158Smillert
906*b39c5158Smillert=item C<T_NOTWINDOWCOMPAT> (1)
907*b39c5158Smillert
908*b39c5158SmillertApplication type is not-window-compatible.
909*b39c5158Smillert
910*b39c5158Smillert=item C<T_WINDOWCOMPAT> (2)
911*b39c5158Smillert
912*b39c5158SmillertApplication type is window-compatible.
913*b39c5158Smillert
914*b39c5158Smillert=item C<T_WINDOWAPI> (3)
915*b39c5158Smillert
916*b39c5158SmillertApplication type is window-API.
917*b39c5158Smillert
918*b39c5158Smillert=back
919*b39c5158Smillert
920*b39c5158SmillertThe remaining bits should be masked with the following values to
921*b39c5158Smillertdetermine the type of the executable:
922*b39c5158Smillert
923*b39c5158Smillert=over
924*b39c5158Smillert
925*b39c5158Smillert=item C<T_BOUND> (8)
926*b39c5158Smillert
927*b39c5158SmillertSet to 1 if the executable file has been "bound" (by the BIND command)
928*b39c5158Smillertas a Family API application. Bits 0, 1, and 2 still apply.
929*b39c5158Smillert
930*b39c5158Smillert=item C<T_DLL> (0x10)
931*b39c5158Smillert
932*b39c5158SmillertSet to 1 if the executable file is a dynamic link library (DLL)
933*b39c5158Smillertmodule. Bits 0, 1, 2, 3, and 5 will be set to 0.
934*b39c5158Smillert
935*b39c5158Smillert=item C<T_DOS> (0x20)
936*b39c5158Smillert
937*b39c5158SmillertSet to 1 if the executable file is in PC/DOS format. Bits 0, 1, 2, 3,
938*b39c5158Smillertand 4 will be set to 0.
939*b39c5158Smillert
940*b39c5158Smillert=item C<T_PHYSDRV> (0x40)
941*b39c5158Smillert
942*b39c5158SmillertSet to 1 if the executable file is a physical device driver.
943*b39c5158Smillert
944*b39c5158Smillert=item C<T_VIRTDRV> (0x80)
945*b39c5158Smillert
946*b39c5158SmillertSet to 1 if the executable file is a virtual device driver.
947*b39c5158Smillert
948*b39c5158Smillert=item C<T_PROTDLL> (0x100)
949*b39c5158Smillert
950*b39c5158SmillertSet to 1 if the executable file is a protected-memory dynamic link
951*b39c5158Smillertlibrary module.
952*b39c5158Smillert
953*b39c5158Smillert=item C<T_32BIT> (0x4000)
954*b39c5158Smillert
955*b39c5158SmillertSet to 1 for 32-bit executable files.
956*b39c5158Smillert
957*b39c5158Smillert=back
958*b39c5158Smillert
959*b39c5158Smillertfile_type() may croak with one of the strings C<"Invalid EXE
960*b39c5158Smillertsignature"> or C<"EXE marked invalid"> to indicate typical error
961*b39c5158Smillertconditions.  If given non-absolute path, will look on C<PATH>, will
962*b39c5158Smillertadd extension F<.exe> if no extension is present (add extension F<.>
963*b39c5158Smillertto suppress).
964*b39c5158Smillert
965*b39c5158Smillert=item C<@list = process_codepages()>
966*b39c5158Smillert
967*b39c5158Smillertthe first element is the currently active codepage, up to 2 additional
968*b39c5158Smillertentries specify the system's "prepared codepages": the codepages the
969*b39c5158Smillertuser can switch to.  The active codepage of a process is one of the
970*b39c5158Smillertprepared codepages of the system (if present).
971*b39c5158Smillert
972*b39c5158Smillert=item C<process_codepage_set($cp)>
973*b39c5158Smillert
974*b39c5158Smillertsets the currently active codepage.  [Affects printer output, in/out
975*b39c5158Smillertcodepages of sessions started by this process, and the default
976*b39c5158Smillertcodepage for drawing in PM; is inherited by kids.  Does not affect the
977*b39c5158Smillertout- and in-codepages of the session.]
978*b39c5158Smillert
979*b39c5158Smillert=item ppid()
980*b39c5158Smillert
981*b39c5158Smillertreturns the PID of the parent process.
982*b39c5158Smillert
983*b39c5158Smillert=item C<ppidOf($pid = $$)>
984*b39c5158Smillert
985*b39c5158Smillertreturns the PID of the parent process of $pid.  -1 on error.
986*b39c5158Smillert
987*b39c5158Smillert=item C<sidOf($pid = $$)>
988*b39c5158Smillert
989*b39c5158Smillertreturns the session id of the process id $pid.  -1 on error.
990*b39c5158Smillert
991*b39c5158Smillert=back
992*b39c5158Smillert
993*b39c5158Smillert=head2 Control of VIO sessions
994*b39c5158Smillert
995*b39c5158SmillertVIO applications are applications running in a text-mode session.
996*b39c5158Smillert
997*b39c5158Smillert=over
998*b39c5158Smillert
999*b39c5158Smillert=item out_codepage()
1000*b39c5158Smillert
1001*b39c5158Smillertgets code page used for screen output (glyphs).  -1 means that a user font
1002*b39c5158Smillertwas loaded.
1003*b39c5158Smillert
1004*b39c5158Smillert=item C<out_codepage_set($cp)>
1005*b39c5158Smillert
1006*b39c5158Smillertsets code page used for screen output (glyphs).  -1 switches to a preloaded
1007*b39c5158Smillertuser font.  -2 switches off the preloaded user font.
1008*b39c5158Smillert
1009*b39c5158Smillert=item in_codepage()
1010*b39c5158Smillert
1011*b39c5158Smillertgets code page used for keyboard input.  0 means that a hardware codepage
1012*b39c5158Smillertis used.
1013*b39c5158Smillert
1014*b39c5158Smillert=item C<in_codepage_set($cp)>
1015*b39c5158Smillert
1016*b39c5158Smillertsets code page used for keyboard input.
1017*b39c5158Smillert
1018*b39c5158Smillert=item C<($w, $h) = scrsize()>
1019*b39c5158Smillert
1020*b39c5158Smillertwidth and height of the given console window in character cells.
1021*b39c5158Smillert
1022*b39c5158Smillert=item C<scrsize_set([$w, ] $h)>
1023*b39c5158Smillert
1024*b39c5158Smillertset height (and optionally width) of the given console window in
1025*b39c5158Smillertcharacter cells.  Use 0 size to keep the old size.
1026*b39c5158Smillert
1027*b39c5158Smillert=item C<($s, $e, $w, $a) = cursor()>
1028*b39c5158Smillert
1029*b39c5158Smillertgets start/end lines of the blinking cursor in the charcell, its width
1030*b39c5158Smillert(1 on text modes) and attribute (-1 for hidden, in text modes other
1031*b39c5158Smillertvalues mean visible, in graphic modes color).
1032*b39c5158Smillert
1033*b39c5158Smillert=item C<cursor_set($s, $e, [$w [, $a]])>
1034*b39c5158Smillert
1035*b39c5158Smillertsets start/end lines of the blinking cursor in the charcell.  Negative
1036*b39c5158Smillertvalues mean percents of the character cell height.
1037*b39c5158Smillert
1038*b39c5158Smillert=item screen()
1039*b39c5158Smillert
1040*b39c5158Smillertgets a buffer with characters and attributes of the screen.
1041*b39c5158Smillert
1042*b39c5158Smillert=item C<screen_set($buffer)>
1043*b39c5158Smillert
1044*b39c5158Smillertrestores the screen given the result of screen().  E.g., if the file
1045*b39c5158SmillertC<$file> contains the screen contents, then
1046*b39c5158Smillert
1047*b39c5158Smillert  open IN, $file or die;
1048*b39c5158Smillert  binmode IN;
1049*b39c5158Smillert  read IN, $in, -s IN;
1050*b39c5158Smillert  $s = screen;
1051*b39c5158Smillert  $in .= qq(\0) x (length($s) - length $in);
1052*b39c5158Smillert  substr($in, length $s) = '';
1053*b39c5158Smillert  screen_set $in;
1054*b39c5158Smillert
1055*b39c5158Smillertwill restore the screen content even if the height of the window
1056*b39c5158Smillertchanged (if the width changed, more manipulation is needed).
1057*b39c5158Smillert
1058*b39c5158Smillert=back
1059*b39c5158Smillert
1060*b39c5158Smillert=head2 Control of the process list
1061*b39c5158Smillert
1062*b39c5158SmillertWith the exception of Title_set(), all these calls require that PM is
1063*b39c5158Smillertrunning, they would not work under alternative Session Managers.
1064*b39c5158Smillert
1065*b39c5158Smillert=over
1066*b39c5158Smillert
1067*b39c5158Smillert=item process_entry()
1068*b39c5158Smillert
1069*b39c5158Smillertreturns a list of the following data:
1070*b39c5158Smillert
1071*b39c5158Smillert=over
1072*b39c5158Smillert
1073*b39c5158Smillert=item *
1074*b39c5158Smillert
1075*b39c5158SmillertTitle of the process (in the C<Ctrl-Esc> list);
1076*b39c5158Smillert
1077*b39c5158Smillert=item *
1078*b39c5158Smillert
1079*b39c5158Smillertwindow handle of switch entry of the process (in the C<Ctrl-Esc> list);
1080*b39c5158Smillert
1081*b39c5158Smillert=item *
1082*b39c5158Smillert
1083*b39c5158Smillertwindow handle of the icon of the process;
1084*b39c5158Smillert
1085*b39c5158Smillert=item *
1086*b39c5158Smillert
1087*b39c5158Smillertprocess handle of the owner of the entry in C<Ctrl-Esc> list;
1088*b39c5158Smillert
1089*b39c5158Smillert=item *
1090*b39c5158Smillert
1091*b39c5158Smillertprocess id of the owner of the entry in C<Ctrl-Esc> list;
1092*b39c5158Smillert
1093*b39c5158Smillert=item *
1094*b39c5158Smillert
1095*b39c5158Smillertsession id of the owner of the entry in C<Ctrl-Esc> list;
1096*b39c5158Smillert
1097*b39c5158Smillert=item *
1098*b39c5158Smillert
1099*b39c5158Smillertwhether visible in C<Ctrl-Esc> list;
1100*b39c5158Smillert
1101*b39c5158Smillert=item *
1102*b39c5158Smillert
1103*b39c5158Smillertwhether item cannot be switched to (note that it is not actually
1104*b39c5158Smillertgrayed in the C<Ctrl-Esc> list));
1105*b39c5158Smillert
1106*b39c5158Smillert=item *
1107*b39c5158Smillert
1108*b39c5158Smillertwhether participates in jump sequence;
1109*b39c5158Smillert
1110*b39c5158Smillert=item *
1111*b39c5158Smillert
1112*b39c5158Smillertprogram type.  Possible values are:
1113*b39c5158Smillert
1114*b39c5158Smillert     PROG_DEFAULT                       0
1115*b39c5158Smillert     PROG_FULLSCREEN                    1
1116*b39c5158Smillert     PROG_WINDOWABLEVIO                 2
1117*b39c5158Smillert     PROG_PM                            3
1118*b39c5158Smillert     PROG_VDM                           4
1119*b39c5158Smillert     PROG_WINDOWEDVDM                   7
1120*b39c5158Smillert
1121*b39c5158SmillertAlthough there are several other program types for WIN-OS/2 programs,
1122*b39c5158Smillertthese do not show up in this field. Instead, the PROG_VDM or
1123*b39c5158SmillertPROG_WINDOWEDVDM program types are used. For instance, for
1124*b39c5158SmillertPROG_31_STDSEAMLESSVDM, PROG_WINDOWEDVDM is used. This is because all
1125*b39c5158Smillertthe WIN-OS/2 programs run in DOS sessions. For example, if a program
1126*b39c5158Smillertis a windowed WIN-OS/2 program, it runs in a PROG_WINDOWEDVDM
1127*b39c5158Smillertsession. Likewise, if it's a full-screen WIN-OS/2 program, it runs in
1128*b39c5158Smillerta PROG_VDM session.
1129*b39c5158Smillert
1130*b39c5158Smillert=item *
1131*b39c5158Smillert
1132*b39c5158Smillertswitch-entry handle.
1133*b39c5158Smillert
1134*b39c5158Smillert=back
1135*b39c5158Smillert
1136*b39c5158SmillertOptional arguments: the pid and the window-handle of the application running
1137*b39c5158Smillertin the OS/2 session to query.
1138*b39c5158Smillert
1139*b39c5158Smillert=item process_hentry()
1140*b39c5158Smillert
1141*b39c5158Smillertsimilar to process_entry(), but returns a hash reference, the keys being
1142*b39c5158Smillert
1143*b39c5158Smillert  title owner_hwnd icon_hwnd owner_phandle owner_pid owner_sid
1144*b39c5158Smillert  visible nonswitchable jumpable ptype sw_entry
1145*b39c5158Smillert
1146*b39c5158Smillert(a copy of the list of keys is in @hentry_fields).
1147*b39c5158Smillert
1148*b39c5158Smillert=item process_entries()
1149*b39c5158Smillert
1150*b39c5158Smillertsimilar to process_entry(), but returns a list of array reference for all
1151*b39c5158Smillertthe elements in the switch list (one controlling C<Ctrl-Esc> window).
1152*b39c5158Smillert
1153*b39c5158Smillert=item process_hentries()
1154*b39c5158Smillert
1155*b39c5158Smillertsimilar to process_hentry(), but returns a list of hash reference for all
1156*b39c5158Smillertthe elements in the switch list (one controlling C<Ctrl-Esc> window).
1157*b39c5158Smillert
1158*b39c5158Smillert=item change_entry()
1159*b39c5158Smillert
1160*b39c5158Smillertchanges a process entry, arguments are the same as process_entry() returns.
1161*b39c5158Smillert
1162*b39c5158Smillert=item change_entryh()
1163*b39c5158Smillert
1164*b39c5158SmillertSimilar to change_entry(), but takes a hash reference as an argument.
1165*b39c5158Smillert
1166*b39c5158Smillert=item process_hwnd()
1167*b39c5158Smillert
1168*b39c5158Smillertreturns the C<owner_hwnd> of the process entry (for VIO windowed processes
1169*b39c5158Smillertthis is the frame window of the session).
1170*b39c5158Smillert
1171*b39c5158Smillert=item Title()
1172*b39c5158Smillert
1173*b39c5158Smillertreturns the text of the task switch menu entry of the current session.
1174*b39c5158Smillert(There is no way to get this info in non-standard Session Managers.  This
1175*b39c5158Smillertimplementation is a shortcut via process_entry().)
1176*b39c5158Smillert
1177*b39c5158Smillert=item C<Title_set(newtitle)>
1178*b39c5158Smillert
1179*b39c5158Smillerttries two different interfaces.  The Session Manager one does not work
1180*b39c5158Smillertwith some windows (if the title is set from the start).
1181*b39c5158SmillertThis is a limitation of OS/2, in such a case $^E is set to 372 (type
1182*b39c5158Smillert
1183*b39c5158Smillert  help 372
1184*b39c5158Smillert
1185*b39c5158Smillertfor a funny - and wrong  - explanation ;-).  In such cases a
1186*b39c5158Smillertdirect-manipulation of low-level entries is used (same as bothTitle_set()).
1187*b39c5158SmillertKeep in mind that some versions of OS/2 leak memory with such a manipulation.
1188*b39c5158Smillert
1189*b39c5158Smillert=item winTitle()
1190*b39c5158Smillert
1191*b39c5158Smillertreturns text of the titlebar of the current process' window.
1192*b39c5158Smillert
1193*b39c5158Smillert=item C<winTitle_set(newtitle)>
1194*b39c5158Smillert
1195*b39c5158Smillertsets text of the titlebar of the current process' window.  The change does not
1196*b39c5158Smillertaffect the text of the switch entry of the current window.
1197*b39c5158Smillert
1198*b39c5158Smillert=item C<swTitle_set(newtitle)>
1199*b39c5158Smillert
1200*b39c5158Smillertsets text of the task switch menu entry of the current process' window.  [There
1201*b39c5158Smillertis no API to query this title.]  Does it via SwitchEntry interface,
1202*b39c5158Smillertnot Session manager interface.  The change does not affect the text of the
1203*b39c5158Smillerttitlebar of the current window.
1204*b39c5158Smillert
1205*b39c5158Smillert=item C<bothTitle_set(newtitle)>
1206*b39c5158Smillert
1207*b39c5158Smillertsets text of the titlebar and task switch menu of the current process' window
1208*b39c5158Smillertvia direct manipulation of the windows' texts.
1209*b39c5158Smillert
1210*b39c5158Smillert=item C<SwitchToProgram([$sw_entry])>
1211*b39c5158Smillert
1212*b39c5158Smillertswitch to session given by a switch list handle (defaults to the entry of our process).
1213*b39c5158Smillert
1214*b39c5158SmillertUse of this function causes another window (and its related windows)
1215*b39c5158Smillertof a PM session to appear on the front of the screen, or a switch to
1216*b39c5158Smillertanother session in the case of a non-PM program. In either case,
1217*b39c5158Smillertthe keyboard (and mouse for the non-PM case) input is directed to
1218*b39c5158Smillertthe new program.
1219*b39c5158Smillert
1220*b39c5158Smillert=back
1221*b39c5158Smillert
1222*b39c5158Smillert=head2 Control of the PM windows
1223*b39c5158Smillert
1224*b39c5158SmillertSome of these API's require sending a message to the specified window.
1225*b39c5158SmillertIn such a case the process needs to be a PM process, or to be morphed
1226*b39c5158Smillertto a PM process via OS2::MorphPM().
1227*b39c5158Smillert
1228*b39c5158SmillertFor a temporary morphing to PM use the L<OS2::localMorphPM> class.
1229*b39c5158Smillert
1230*b39c5158SmillertKeep in mind that PM windows are engaged in 2 "orthogonal" window
1231*b39c5158Smillerttrees, as well as in the z-order list.
1232*b39c5158Smillert
1233*b39c5158SmillertOne tree is given by the I<parent/child> relationship.  This
1234*b39c5158Smillertrelationship affects drawing (child is drawn relative to its parent
1235*b39c5158Smillert(lower-left corner), and the drawing is clipped by the parent's
1236*b39c5158Smillertboundary; parent may request that I<it's> drawing is clipped to be
1237*b39c5158Smillertconfined to the outsize of the childs and/or siblings' windows);
1238*b39c5158Smillerthiding; minimizing/restoring; and destroying windows.
1239*b39c5158Smillert
1240*b39c5158SmillertAnother tree (not necessarily connected?) is given by I<ownership>
1241*b39c5158Smillertrelationship.  Ownership relationship assumes cooperation of the
1242*b39c5158Smillertengaged windows via passing messages on "important events"; e.g.,
1243*b39c5158Smillertscrollbars send information messages when the "bar" is moved, menus
1244*b39c5158Smillertsend messages when an item is selected; frames
1245*b39c5158Smillertmove/hide/unhide/minimize/restore/change-z-order-of owned frames when
1246*b39c5158Smillertthe owner is moved/etc., and destroy the owned frames (even when these
1247*b39c5158Smillertframes are not descendants) when the owner is destroyed; etc.  [An
1248*b39c5158Smillertimportant restriction on ownership is that owner should be created by
1249*b39c5158Smillertthe same thread as the owned thread, so they engage in the same
1250*b39c5158Smillertmessage queue.]
1251*b39c5158Smillert
1252*b39c5158SmillertWindows may be in many different state: Focused (take keyboard events) or not,
1253*b39c5158SmillertActivated (=Frame windows in the I<parent/child> tree between the root and
1254*b39c5158Smillertthe window with the focus; usually indicate such "active state" by titlebar
1255*b39c5158Smillerthighlights, and take mouse events) or not, Enabled/Disabled (this influences
1256*b39c5158Smillertthe ability to update the graphic, and may change appearance, as for
1257*b39c5158Smillertenabled/disabled buttons), Visible/Hidden, Minimized/Maximized/Restored, Modal
1258*b39c5158Smillertor not, etc.
1259*b39c5158Smillert
1260*b39c5158SmillertThe APIs below all die() on error with the message being $^E.
1261*b39c5158Smillert
1262*b39c5158Smillert=over
1263*b39c5158Smillert
1264*b39c5158Smillert=item C<WindowText($hwnd)>
1265*b39c5158Smillert
1266*b39c5158Smillertgets "a text content" of a window.  Requires (morphing to) PM.
1267*b39c5158Smillert
1268*b39c5158Smillert=item C<WindowText_set($hwnd, $text)>
1269*b39c5158Smillert
1270*b39c5158Smillertsets "a text content" of a window.  Requires (morphing to) PM.
1271*b39c5158Smillert
1272*b39c5158Smillert=item C<($x, $y, $flags, $width, $height, $behind, @rest) = WindowPos($hwnd)>
1273*b39c5158Smillert
1274*b39c5158Smillertgets window position info as 8 integers (of C<SWP>), in the order suitable
1275*b39c5158Smillertfor WindowPos_set().  @rest is marked as "reserved" in PM docs.  $flags
1276*b39c5158Smillertis a combination of C<SWP_*> constants.
1277*b39c5158Smillert
1278*b39c5158Smillert=item C<$hash = hWindowPos($hwnd)>
1279*b39c5158Smillert
1280*b39c5158Smillertgets window position info as a hash reference; the keys are C<flags width
1281*b39c5158Smillertheight x y behind hwnd reserved1 reserved2>.
1282*b39c5158Smillert
1283*b39c5158SmillertExample:
1284*b39c5158Smillert
1285*b39c5158Smillert  exit unless $hash->{flags} & SWP_MAXIMIZE;	# Maximized
1286*b39c5158Smillert
1287*b39c5158Smillert=item C<WindowPos_set($hwnd, $x, $y, $flags = SWP_MOVE, $width = 0, $height = 0, $behind = HWND_TOP)>
1288*b39c5158Smillert
1289*b39c5158SmillertSet state of the window: position, size, zorder, show/hide, activation,
1290*b39c5158Smillertminimize/maximize/restore etc.  Which of these operations to perform
1291*b39c5158Smillertis governed by $flags.
1292*b39c5158Smillert
1293*b39c5158Smillert=item C<hWindowPos_set($hash, [$hwnd])>
1294*b39c5158Smillert
1295*b39c5158SmillertSame as C<WindowPos_set>, but takes the position from keys C<fl width height
1296*b39c5158Smillertx y behind hwnd> of the hash referenced by $hash.  If $hwnd is explicitly
1297*b39c5158Smillertspecified, it overrides C<< $hash->{hwnd} >>.  If $hash->{flags} is not specified,
1298*b39c5158Smillertit is calculated basing on the existing keys of $hash.  Requires (morphing to) PM.
1299*b39c5158Smillert
1300*b39c5158SmillertExample:
1301*b39c5158Smillert
1302*b39c5158Smillert  hWindowPos_set {flags => SWP_MAXIMIZE}, $hwnd; # Maximize
1303*b39c5158Smillert
1304*b39c5158Smillert=item C<($pid, $tid) = WindowProcess($hwnd)>
1305*b39c5158Smillert
1306*b39c5158Smillertgets I<PID> and I<TID> of the process associated to the window.
1307*b39c5158Smillert
1308*b39c5158Smillert=item C<ClassName($hwnd)>
1309*b39c5158Smillert
1310*b39c5158Smillertreturns the class name of the window.
1311*b39c5158Smillert
1312*b39c5158SmillertIf this window is of any of the preregistered WC_* classes the class
1313*b39c5158Smillertname returned is in the form "#nnnnn", where "nnnnn" is a group
1314*b39c5158Smillertof up to five digits that corresponds to the value of the WC_* class name
1315*b39c5158Smillertconstant.
1316*b39c5158Smillert
1317*b39c5158Smillert=item WindowStyle($hwnd)
1318*b39c5158Smillert
1319*b39c5158SmillertReturns the "window style" flags for window handle $hwnd.
1320*b39c5158Smillert
1321*b39c5158Smillert=item WindowULong($hwnd, $id), WindowPtr($hwnd, $id), WindowUShort($hwnd, $id)
1322*b39c5158Smillert
1323*b39c5158SmillertReturn data associated to window handle $hwnd.  $id should be one of
1324*b39c5158SmillertC<QWL_*>, C<QWP_PFNWP>, C<QWS_*> constants, or a byte offset referencing
1325*b39c5158Smillerta region (of length 4, 4, 2 correspondingly) fully inside C<0..cbWindowData-1>.
1326*b39c5158SmillertHere C<cbWindowData> is the count of extra user-specified bytes reserved
1327*b39c5158Smillertfor the given class of windows.
1328*b39c5158Smillert
1329*b39c5158Smillert=item WindowULong_set($hwnd, $id, $value), WindowPtr_set, WindowUShort_set
1330*b39c5158Smillert
1331*b39c5158SmillertSimilar to WindowULong(), WindowPtr(), WindowUShort(), but for assigning the
1332*b39c5158Smillertvalue $value.
1333*b39c5158Smillert
1334*b39c5158Smillert=item WindowBits_set($hwnd, $id, $value, $mask)
1335*b39c5158Smillert
1336*b39c5158SmillertSimilar to WindowULong_set(), but will change only the bits which are
1337*b39c5158Smillertset in $mask.
1338*b39c5158Smillert
1339*b39c5158Smillert=item FocusWindow()
1340*b39c5158Smillert
1341*b39c5158Smillertreturns the handle of the focus window.  Optional argument for specifying
1342*b39c5158Smillertthe desktop to use.
1343*b39c5158Smillert
1344*b39c5158Smillert=item C<FocusWindow_set($hwnd)>
1345*b39c5158Smillert
1346*b39c5158Smillertset the focus window by handle.  Optional argument for specifying the desktop
1347*b39c5158Smillertto use.  E.g, the first entry in program_entries() is the C<Ctrl-Esc> list.
1348*b39c5158SmillertTo show an application, use either one of
1349*b39c5158Smillert
1350*b39c5158Smillert       WinShowWindow( $hwnd, 1 );
1351*b39c5158Smillert       FocusWindow_set( $hwnd );
1352*b39c5158Smillert       SwitchToProgram($switch_handle);
1353*b39c5158Smillert
1354*b39c5158Smillert(Which work with alternative focus-to-front policies?)  Requires
1355*b39c5158Smillert(morphing to) PM.
1356*b39c5158Smillert
1357*b39c5158SmillertSwitching focus to currently-unfocused window moves the window to the
1358*b39c5158Smillertfront in Z-order; use FocusWindow_set_keep_Zorder() to avoid this.
1359*b39c5158Smillert
1360*b39c5158Smillert=item C<FocusWindow_set_keep_Zorder($hwnd)>
1361*b39c5158Smillert
1362*b39c5158Smillertsame as FocusWindow_set(), but preserves the Z-order of windows.
1363*b39c5158Smillert
1364*b39c5158Smillert=item C<ActiveWindow([$parentHwnd])>
1365*b39c5158Smillert
1366*b39c5158Smillertgets the active subwindow's handle for $parentHwnd or desktop.
1367*b39c5158SmillertReturns FALSE if none.
1368*b39c5158Smillert
1369*b39c5158Smillert=item C<ActiveWindow_set($hwnd, [$parentHwnd])>
1370*b39c5158Smillert
1371*b39c5158Smillertsets the active subwindow's handle for $parentHwnd or desktop.  Requires (morphing to) PM.
1372*b39c5158Smillert
1373*b39c5158Smillert=item C<ShowWindow($hwnd [, $show])>
1374*b39c5158Smillert
1375*b39c5158SmillertSet visible/hidden flag of the window.  Default: $show is TRUE.
1376*b39c5158Smillert
1377*b39c5158Smillert=item C<EnableWindowUpdate($hwnd [, $update])>
1378*b39c5158Smillert
1379*b39c5158SmillertSet window visibility state flag for the window for subsequent drawing.
1380*b39c5158SmillertNo actual drawing is done at this moment.  Use C<ShowWindow($hwnd, $state)>
1381*b39c5158Smillertwhen redrawing is needed.  While update is disabled, changes to the "window
1382*b39c5158Smillertstate" do not change the appearance of the window.  Default: $update is TRUE.
1383*b39c5158Smillert
1384*b39c5158Smillert(What is manipulated is the bit C<WS_VISIBLE> of the window style.)
1385*b39c5158Smillert
1386*b39c5158Smillert=item C<EnableWindow($hwnd [, $enable])>
1387*b39c5158Smillert
1388*b39c5158SmillertSet the window enabled state.  Default: $enable is TRUE.
1389*b39c5158Smillert
1390*b39c5158SmillertResults in C<WM_ENABLED> message sent to the window.  Typically, this
1391*b39c5158Smillertwould change the appearence of the window.  If at the moment of disabling
1392*b39c5158Smillertfocus is in the window (or a descendant), focus is lost (no focus anywhere).
1393*b39c5158SmillertIf focus is needed, it can be reassigned explicitly later.
1394*b39c5158Smillert
1395*b39c5158Smillert=item IsWindowEnabled(), IsWindowVisible(), IsWindowShowing()
1396*b39c5158Smillert
1397*b39c5158Smillertthese functions take $hwnd as an argument.  IsWindowEnabled() queries
1398*b39c5158Smillertthe state changed by EnableWindow(), IsWindowVisible() the state changed
1399*b39c5158Smillertby ShowWindow(), IsWindowShowing() is true if there is a part of the window
1400*b39c5158Smillertvisible on the screen.
1401*b39c5158Smillert
1402*b39c5158Smillert=item C<PostMsg($hwnd, $msg, $mp1, $mp2)>
1403*b39c5158Smillert
1404*b39c5158Smillertpost message to a window.  The meaning of $mp1, $mp2 is specific for each
1405*b39c5158Smillertmessage id $msg, they default to 0.  E.g.,
1406*b39c5158Smillert
1407*b39c5158Smillert  use OS2::Process qw(:DEFAULT WM_SYSCOMMAND WM_CONTEXTMENU
1408*b39c5158Smillert		      WM_SAVEAPPLICATION WM_QUIT WM_CLOSE
1409*b39c5158Smillert		      SC_MAXIMIZE SC_RESTORE);
1410*b39c5158Smillert  $hwnd = process_hentry()->{owner_hwnd};
1411*b39c5158Smillert  # Emulate choosing `Restore' from the window menu:
1412*b39c5158Smillert  PostMsg $hwnd, WM_SYSCOMMAND, MPFROMSHORT(SC_RESTORE); # Not immediate
1413*b39c5158Smillert
1414*b39c5158Smillert  # Emulate `Show-Contextmenu' (Double-Click-2), two ways:
1415*b39c5158Smillert  PostMsg ActiveWindow, WM_CONTEXTMENU;
1416*b39c5158Smillert  PostMsg FocusWindow, WM_CONTEXTMENU;
1417*b39c5158Smillert
1418*b39c5158Smillert  /* Emulate `Close' */
1419*b39c5158Smillert  PostMsg ActiveWindow, WM_CLOSE;
1420*b39c5158Smillert
1421*b39c5158Smillert  /* Same but with some "warnings" to the application */
1422*b39c5158Smillert  $hwnd = ActiveWindow;
1423*b39c5158Smillert  PostMsg $hwnd, WM_SAVEAPPLICATION;
1424*b39c5158Smillert  PostMsg $hwnd, WM_CLOSE;
1425*b39c5158Smillert  PostMsg $hwnd, WM_QUIT;
1426*b39c5158Smillert
1427*b39c5158SmillertIn fact, MPFROMSHORT() may be omitted above.
1428*b39c5158Smillert
1429*b39c5158SmillertFor messages to other processes, messages which take/return a pointer are
1430*b39c5158Smillertnot supported.
1431*b39c5158Smillert
1432*b39c5158Smillert=item C<MP*()>
1433*b39c5158Smillert
1434*b39c5158SmillertThe functions MPFROMSHORT(), MPVOID(), MPFROMCHAR(), MPFROM2SHORT(),
1435*b39c5158SmillertMPFROMSH2CH(), MPFROMLONG() can be used the same way as from C.  Use them
1436*b39c5158Smillertto construct parameters $m1, $m2 to PostMsg().
1437*b39c5158Smillert
1438*b39c5158SmillertThese functions are not exported by default.
1439*b39c5158Smillert
1440*b39c5158Smillert=item C<$eh = BeginEnumWindows($hwnd)>
1441*b39c5158Smillert
1442*b39c5158Smillertstarts enumerating immediate child windows of $hwnd in z-order.  The
1443*b39c5158Smillertenumeration reflects the state at the moment of BeginEnumWindows() calls;
1444*b39c5158Smillertuse IsWindow() to be sure.  All the functions in this group require (morphing to) PM.
1445*b39c5158Smillert
1446*b39c5158Smillert=item C<$kid_hwnd = GetNextWindow($eh)>
1447*b39c5158Smillert
1448*b39c5158Smillertgets the next kid in the list.  Gets 0 on error or when the list ends.
1449*b39c5158Smillert
1450*b39c5158Smillert=item C<EndEnumWindows($eh)>
1451*b39c5158Smillert
1452*b39c5158SmillertEnd enumeration and release the list.
1453*b39c5158Smillert
1454*b39c5158Smillert=item C<@list = ChildWindows([$hwnd])>
1455*b39c5158Smillert
1456*b39c5158Smillertreturns the list of child windows at the moment of the call.  Same remark
1457*b39c5158Smillertas for enumeration interface applies.  Defaults to HWND_DESKTOP.
1458*b39c5158SmillertExample of usage:
1459*b39c5158Smillert
1460*b39c5158Smillert  sub l {
1461*b39c5158Smillert    my ($o,$h) = @_;
1462*b39c5158Smillert    printf ' ' x $o . "%#x\n", $h;
1463*b39c5158Smillert    l($o+2,$_) for ChildWindows $h;
1464*b39c5158Smillert  }
1465*b39c5158Smillert  l 0, $HWND_DESKTOP
1466*b39c5158Smillert
1467*b39c5158Smillert=item C<IsWindow($hwnd)>
1468*b39c5158Smillert
1469*b39c5158Smillerttrue if the window handle is still valid.
1470*b39c5158Smillert
1471*b39c5158Smillert=item C<QueryWindow($hwnd, $type)>
1472*b39c5158Smillert
1473*b39c5158Smillertgets the handle of a related window.  $type should be one of C<QW_*> constants.
1474*b39c5158Smillert
1475*b39c5158Smillert=item C<IsChild($hwnd, $parent)>
1476*b39c5158Smillert
1477*b39c5158Smillertreturn TRUE if $hwnd is a descendant of $parent.
1478*b39c5158Smillert
1479*b39c5158Smillert=item C<WindowFromId($hwnd, $id)>
1480*b39c5158Smillert
1481*b39c5158Smillertreturn a window handle of a child of $hwnd with the given $id.
1482*b39c5158Smillert
1483*b39c5158Smillert  hwndSysMenu = WinWindowFromID(hwndDlg, FID_SYSMENU);
1484*b39c5158Smillert  WinSendMsg(hwndSysMenu, MM_SETITEMATTR,
1485*b39c5158Smillert      MPFROM2SHORT(SC_CLOSE, TRUE),
1486*b39c5158Smillert      MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
1487*b39c5158Smillert
1488*b39c5158Smillert=item C<WindowFromPoint($x, $y [, $hwndParent [, $descedantsToo]])>
1489*b39c5158Smillert
1490*b39c5158Smillertgets a handle of a child of $hwndParent at C<($x,$y)>.  If $descedantsToo
1491*b39c5158Smillert(defaulting to 1) then children of children may be returned too.  May return
1492*b39c5158Smillert$hwndParent (defaults to desktop) if no suitable children are found,
1493*b39c5158Smillertor 0 if the point is outside the parent.
1494*b39c5158Smillert
1495*b39c5158Smillert$x and $y are relative to $hwndParent.
1496*b39c5158Smillert
1497*b39c5158Smillert=item C<EnumDlgItem($dlgHwnd, $type [, $relativeHwnd])>
1498*b39c5158Smillert
1499*b39c5158Smillertgets a dialog item window handle for an item of type $type of $dlgHwnd
1500*b39c5158Smillertrelative to $relativeHwnd, which is descendant of $dlgHwnd.
1501*b39c5158Smillert$relativeHwnd may be specified if $type is EDI_FIRSTTABITEM or
1502*b39c5158SmillertEDI_LASTTABITEM.
1503*b39c5158Smillert
1504*b39c5158SmillertThe return is always an immediate child of hwndDlg, even if hwnd is
1505*b39c5158Smillertnot an immediate child window.  $type may be
1506*b39c5158Smillert
1507*b39c5158Smillert=over
1508*b39c5158Smillert
1509*b39c5158Smillert=item EDI_FIRSTGROUPITEM
1510*b39c5158Smillert
1511*b39c5158SmillertFirst item in the same group.
1512*b39c5158Smillert
1513*b39c5158Smillert=item EDI_FIRSTTABITEM
1514*b39c5158Smillert
1515*b39c5158SmillertFirst item in dialog with style WS_TABSTOP. hwnd is ignored.
1516*b39c5158Smillert
1517*b39c5158Smillert=item EDI_LASTGROUPITEM
1518*b39c5158Smillert
1519*b39c5158SmillertLast item in the same group.
1520*b39c5158Smillert
1521*b39c5158Smillert=item EDI_LASTTABITEM
1522*b39c5158Smillert
1523*b39c5158SmillertLast item in dialog with style WS_TABSTOP. hwnd is ignored.
1524*b39c5158Smillert
1525*b39c5158Smillert=item EDI_NEXTGROUPITEM
1526*b39c5158Smillert
1527*b39c5158SmillertNext item in the same group. Wraps around to beginning of group when
1528*b39c5158Smillertthe end of the group is reached.
1529*b39c5158Smillert
1530*b39c5158Smillert=item EDI_NEXTTABITEM
1531*b39c5158Smillert
1532*b39c5158SmillertNext item with style WS_TABSTOP. Wraps around to beginning of dialog
1533*b39c5158Smillertitem list when end is reached.
1534*b39c5158Smillert
1535*b39c5158Smillert=item EDI_PREVGROUPITEM
1536*b39c5158Smillert
1537*b39c5158SmillertPrevious item in the same group. Wraps around to end of group when the
1538*b39c5158Smillertstart of the group is reached. For information on the WS_GROUP style,
1539*b39c5158Smillertsee Window Styles.
1540*b39c5158Smillert
1541*b39c5158Smillert=item EDI_PREVTABITEM
1542*b39c5158Smillert
1543*b39c5158SmillertPrevious item with style WS_TABSTOP. Wraps around to end of dialog
1544*b39c5158Smillertitem list when beginning is reached.
1545*b39c5158Smillert
1546*b39c5158Smillert=back
1547*b39c5158Smillert
1548*b39c5158Smillert=item DesktopWindow()
1549*b39c5158Smillert
1550*b39c5158Smillertgets the actual window handle of the PM desktop; most APIs accept the
1551*b39c5158Smillertpseudo-handle C<HWND_DESKTOP> instead.  Keep in mind that the WPS
1552*b39c5158Smillertdesktop (one with WindowText() being C<"Desktop">) is a different beast?!
1553*b39c5158Smillert
1554*b39c5158Smillert=item TopLevel($hwnd)
1555*b39c5158Smillert
1556*b39c5158Smillertgets the toplevel window of $hwnd.
1557*b39c5158Smillert
1558*b39c5158Smillert=item ResetWinError()
1559*b39c5158Smillert
1560*b39c5158SmillertResets $^E.  One may need to call it before the C<Win*>-class APIs which may
1561*b39c5158Smillertreturn 0 during normal operation.  In such a case one should check both
1562*b39c5158Smillertfor return value being zero and $^E being non-zero.  The following APIs
1563*b39c5158Smillertdo ResetWinError() themselves, thus do not need an explicit one:
1564*b39c5158Smillert
1565*b39c5158Smillert  WindowPtr
1566*b39c5158Smillert  WindowULong
1567*b39c5158Smillert  WindowUShort
1568*b39c5158Smillert  WindowTextLength
1569*b39c5158Smillert  ActiveWindow
1570*b39c5158Smillert  PostMsg
1571*b39c5158Smillert
1572*b39c5158SmillertThis function is normally not needed.  Not exported by default.
1573*b39c5158Smillert
1574*b39c5158Smillert=back
1575*b39c5158Smillert
1576*b39c5158Smillert=head2 Control of the PM data
1577*b39c5158Smillert
1578*b39c5158Smillert=over
1579*b39c5158Smillert
1580*b39c5158Smillert=item ActiveDesktopPathname()
1581*b39c5158Smillert
1582*b39c5158Smillertgets the path of the directory which corresponds to Desktop.
1583*b39c5158Smillert
1584*b39c5158Smillert=item 	InvalidateRect
1585*b39c5158Smillert
1586*b39c5158Smillert=item	CreateFrameControls
1587*b39c5158Smillert
1588*b39c5158Smillert=back
1589*b39c5158Smillert
1590*b39c5158Smillert=head2 Control of the PM clipboard
1591*b39c5158Smillert
1592*b39c5158Smillert=over
1593*b39c5158Smillert
1594*b39c5158Smillert=item ClipbrdText()
1595*b39c5158Smillert
1596*b39c5158Smillertgets the content of the clipboard.  An optional argument is the format
1597*b39c5158Smillertof the data in the clipboard (defaults to C<CF_TEXT>).  May croak with error
1598*b39c5158SmillertC<PMERR_INVALID_HWND> if no data of given $fmt is present.
1599*b39c5158Smillert
1600*b39c5158SmillertNote that the usual convention is to have clipboard data with
1601*b39c5158SmillertC<"\r\n"> as line separators.  This function will only work with clipboard
1602*b39c5158Smillertdata types which are delimited by C<"\0"> byte (not included in the result).
1603*b39c5158Smillert
1604*b39c5158Smillert=item ClipbrdText_2byte
1605*b39c5158Smillert
1606*b39c5158SmillertSame as ClipbrdText(), but will only work with clipboard
1607*b39c5158Smillertdata types which are collection of C C<shorts> delimited by C<0> short
1608*b39c5158Smillert(not included in the result).
1609*b39c5158Smillert
1610*b39c5158Smillert=item ClipbrdTextUCS2le
1611*b39c5158Smillert
1612*b39c5158SmillertSame as ClipbrdText_2byte(), but will assume that the shorts represent
1613*b39c5158Smillertan Unicode string in I<UCS-2le> format (little-endian 2-byte representation
1614*b39c5158Smillertof Unicode), and will provide the result in Perl internal C<utf8> format
1615*b39c5158Smillert(one short of input represents one Perl character).
1616*b39c5158Smillert
1617*b39c5158SmillertNote that Firefox etc. export their selection in unicode types of this format.
1618*b39c5158Smillert
1619*b39c5158Smillert=item ClipbrdText_set($txt, [$no_convert_nl, [$fmt, [$fmtinfo, [$hab] ] ] ] )
1620*b39c5158Smillert
1621*b39c5158Smillertsets the text content of the clipboard after removing old contents.  Unless the
1622*b39c5158Smillertoptional argument  $no_convert_nl is TRUE, will convert newlines to C<"\r\n">.  Another optional
1623*b39c5158Smillertargument $fmt is the format of the data in the clipboard (should be an
1624*b39c5158Smillertatom, defaults to C<CF_TEXT>).  Other arguments are as for C<ClipbrdData_set>.
1625*b39c5158SmillertCroaks on failure.
1626*b39c5158Smillert
1627*b39c5158Smillert=item	ClipbrdFmtInfo( [$fmt, [ $hab ] ])
1628*b39c5158Smillert
1629*b39c5158Smillertreturns the $fmtInfo flags set by the application which filled the
1630*b39c5158Smillertformat $fmt of the clipboard.  $fmt defaults to C<CF_TEXT>.
1631*b39c5158Smillert
1632*b39c5158Smillert=item	ClipbrdOwner( [ $hab ] )
1633*b39c5158Smillert
1634*b39c5158SmillertReturns window handle of the current clipboard owner.
1635*b39c5158Smillert
1636*b39c5158Smillert=item	ClipbrdViewer( [ $hab ] )
1637*b39c5158Smillert
1638*b39c5158SmillertReturns window handle of the current clipboard viewer.
1639*b39c5158Smillert
1640*b39c5158Smillert=item	ClipbrdData( [$fmt, [ $hab ] ])
1641*b39c5158Smillert
1642*b39c5158SmillertReturns a handle to clipboard data of the given format as an integer.
1643*b39c5158SmillertFormat defaults to C<CF_TEXT> (in this case the handle is a memory address).
1644*b39c5158Smillert
1645*b39c5158SmillertClipboard should be opened before calling this function.  May croak with error
1646*b39c5158SmillertC<PMERR_INVALID_HWND> if no data of given $fmt is present.
1647*b39c5158Smillert
1648*b39c5158SmillertThe result should not be used after clipboard is closed.  Hence a return handle
1649*b39c5158Smillertof type C<CLI_POINTER> may need to be converted to a string and stored for
1650*b39c5158Smillertfuture usage.  Use MemoryRegionSize() to get a high estimate on the length
1651*b39c5158Smillertof region addressed by this pointer; the actual length inside this region
1652*b39c5158Smillertshould be obtained by knowing particular format of data.  E.g., it may be
1653*b39c5158Smillert0-byte terminated for string types, or 0-short terminated for wide-char string
1654*b39c5158Smillerttypes.
1655*b39c5158Smillert
1656*b39c5158Smillert=item	OpenClipbrd( [ $hab ] )
1657*b39c5158Smillert
1658*b39c5158Smillertclaim read access to the clipboard.  May need a message queue to operate.
1659*b39c5158SmillertMay block until other processes finish dealing with clipboard.
1660*b39c5158Smillert
1661*b39c5158Smillert=item	CloseClipbrd( [ $hab ] )
1662*b39c5158Smillert
1663*b39c5158SmillertAllow other processes access to clipboard.
1664*b39c5158SmillertClipboard should be opened before calling this function.
1665*b39c5158Smillert
1666*b39c5158Smillert=item	ClipbrdData_set($data, [$convert_nl, [$fmt, [$fmtInfo, [ $hab] ] ] ] )
1667*b39c5158Smillert
1668*b39c5158SmillertSets the clipboard data of format given by atom $fmt.  Format defaults to
1669*b39c5158SmillertCF_TEXT.
1670*b39c5158Smillert
1671*b39c5158Smillert$fmtInfo should declare what type of handle $data is; it should be either
1672*b39c5158SmillertC<CFI_POINTER>, or C<CFI_HANDLE> (possibly qualified by C<CFI_OWNERFREE>
1673*b39c5158Smillertand C<CFI_OWNERDRAW> flags).  It defaults to C<CFI_HANDLE> for $fmt being
1674*b39c5158Smillertstandard bitmap, metafile, and palette (undocumented???) formats;
1675*b39c5158Smillertotherwise defaults to C<CFI_POINTER>.  If format is C<CFI_POINTER>, $data
1676*b39c5158Smillertshould contain the string to copy to clipboard; otherwise it should be an
1677*b39c5158Smillertinteger handle.
1678*b39c5158Smillert
1679*b39c5158SmillertIf $convert_nl is TRUE (the default), C<"\n"> in $data are converted to
1680*b39c5158SmillertC<"\r\n"> pairs if $fmt is C<CFI_POINTER> (as is the convention for text
1681*b39c5158Smillertformat of the clipboard) unless they are already in such a pair.
1682*b39c5158Smillert
1683*b39c5158Smillert=item	_ClipbrdData_set($data, [$fmt, [$fmtInfo, [ $hab] ] ] )
1684*b39c5158Smillert
1685*b39c5158SmillertSets the clipboard data of format given by atom $fmt.  Format defaults to
1686*b39c5158SmillertCF_TEXT.  $data should be an address (in givable unnamed shared memory which
1687*b39c5158Smillertshould not be accessed or manipulated after this call) or a handle in a form
1688*b39c5158Smillertof an integer.
1689*b39c5158Smillert
1690*b39c5158Smillert$fmtInfo has the same semantic as for ClipbrdData_set().
1691*b39c5158Smillert
1692*b39c5158Smillert=item	ClipbrdOwner_set( $hwnd, [ $hab ] )
1693*b39c5158Smillert
1694*b39c5158SmillertSets window handle of the current clipboard owner (window which gets messages
1695*b39c5158Smillertwhen content of clipboard is retrieved).
1696*b39c5158Smillert
1697*b39c5158Smillert=item	ClipbrdViewer_set( $hwnd, [ $hab ] )
1698*b39c5158Smillert
1699*b39c5158SmillertSets window handle of the current clipboard owner (window which gets messages
1700*b39c5158Smillertwhen content of clipboard is changed).
1701*b39c5158Smillert
1702*b39c5158Smillert=item	ClipbrdFmtNames()
1703*b39c5158Smillert
1704*b39c5158SmillertReturns list of names of formats currently available in the clipboard.
1705*b39c5158Smillert
1706*b39c5158Smillert=item	ClipbrdFmtAtoms()
1707*b39c5158Smillert
1708*b39c5158SmillertReturns list of atoms of formats currently available in the clipboard.
1709*b39c5158Smillert
1710*b39c5158Smillert=item	EnumClipbrdFmts($fmt [, $hab])
1711*b39c5158Smillert
1712*b39c5158SmillertLow-level access to the list of formats currently available in the clipboard.
1713*b39c5158SmillertReturns the atom for the format of clipboard after $fmt.  If $fmt is 0, returns
1714*b39c5158Smillertthe first format of clipboard.  Returns 0 if $fmt is the last format.  Example:
1715*b39c5158Smillert
1716*b39c5158Smillert  {
1717*b39c5158Smillert    my $h = OS2::localClipbrd->new('nomorph');
1718*b39c5158Smillert    my $fmt = 0;
1719*b39c5158Smillert    push @formats, AtomName $fmt
1720*b39c5158Smillert      while $fmt = EnumClipbrdFmts $fmt;
1721*b39c5158Smillert  }
1722*b39c5158Smillert
1723*b39c5158SmillertClipboard should be opened before calling this function.  May croak if
1724*b39c5158Smillertno format is present.
1725*b39c5158Smillert
1726*b39c5158Smillert=item	EmptyClipbrd( [ $hab ] )
1727*b39c5158Smillert
1728*b39c5158SmillertRemove all the data handles in the clipboard.  croak()s on failure.
1729*b39c5158SmillertClipboard should be opened before calling this function.
1730*b39c5158Smillert
1731*b39c5158SmillertRecommended before assigning a value to clipboard to remove extraneous
1732*b39c5158Smillertformats of data from clipboard.
1733*b39c5158Smillert
1734*b39c5158Smillert=item ($size, $flags) = MemoryRegionSize($addr, [$size_lim, [ $interrupt ]])
1735*b39c5158Smillert
1736*b39c5158Smillert$addr should be a memory address (encoded as integer).  This call finds
1737*b39c5158Smillertthe largest continuous region of memory belonging to the same memory object
1738*b39c5158Smillertas $addr, and having the same memory flags as $addr. $flags is the value of
1739*b39c5158Smillertthe memory flag of $addr (see docs of DosQueryMem(3) for details).  If
1740*b39c5158Smillertoptional argumetn $size_lim is given, the search is restricted to the region
1741*b39c5158Smillertthis many bytes long (after $addr).
1742*b39c5158Smillert
1743*b39c5158Smillert($addr and $size are rounded so that all the memory pages containing
1744*b39c5158Smillertthe region are inspected.)  Optional argument $interrupt (defaults to 1)
1745*b39c5158Smillertspecifies whether region scan should be interruptable by signals.
1746*b39c5158Smillert
1747*b39c5158Smillert=back
1748*b39c5158Smillert
1749*b39c5158SmillertUse class C<OS2::localClipbrd> to ensure that clipboard is closed even if
1750*b39c5158Smillertthe code in the block made a non-local exit.
1751*b39c5158Smillert
1752*b39c5158SmillertSee the L<OS2::localMorphPM> and L<OS2::localClipbrd> classes.
1753*b39c5158Smillert
1754*b39c5158Smillert=head2 Control of the PM atom tables
1755*b39c5158Smillert
1756*b39c5158SmillertLow-level methods to access the atom table(s).  $atomtable defaults to
1757*b39c5158Smillertthe SystemAtomTable().
1758*b39c5158Smillert
1759*b39c5158Smillert=over
1760*b39c5158Smillert
1761*b39c5158Smillert=item	AddAtom($name, [$atomtable])
1762*b39c5158Smillert
1763*b39c5158SmillertReturns the atom; increments the use count unless $name is a name of an
1764*b39c5158Smillertinteger atom.
1765*b39c5158Smillert
1766*b39c5158Smillert=item	FindAtom($name, [$atomtable])
1767*b39c5158Smillert
1768*b39c5158SmillertReturns the atom if it exists, 0 otherwise (actually, croaks).
1769*b39c5158Smillert
1770*b39c5158Smillert=item	DeleteAtom($name, [$atomtable])
1771*b39c5158Smillert
1772*b39c5158SmillertDecrements the use count unless $name is a name of an integer atom.
1773*b39c5158SmillertWhen count goes to 0, association of the name to an integer is removed.
1774*b39c5158Smillert(Version with prepended underscore returns 0 on success.)
1775*b39c5158Smillert
1776*b39c5158Smillert=item	AtomName($atom, [$atomtable])
1777*b39c5158Smillert
1778*b39c5158SmillertReturns the name of the atom.  Integer atoms have names of format C<"#ddddd">
1779*b39c5158Smillertof variable length up to 7 chars.
1780*b39c5158Smillert
1781*b39c5158Smillert=item	AtomLength($atom, [$atomtable])
1782*b39c5158Smillert
1783*b39c5158SmillertReturns the length of the name of the atom.  Return of 0 means that no
1784*b39c5158Smillertsuch atom exists (but usually croaks in such a case).
1785*b39c5158Smillert
1786*b39c5158SmillertInteger atoms always return length 6.
1787*b39c5158Smillert
1788*b39c5158Smillert=item	AtomUsage($name, [$atomtable])
1789*b39c5158Smillert
1790*b39c5158SmillertReturns the usage count of the atom.
1791*b39c5158Smillert
1792*b39c5158Smillert=item	SystemAtomTable()
1793*b39c5158Smillert
1794*b39c5158SmillertReturns central atom table accessible to any process.
1795*b39c5158Smillert
1796*b39c5158Smillert=item	CreateAtomTable( [ $initial, [ $buckets ] ] )
1797*b39c5158Smillert
1798*b39c5158SmillertReturns new per-process atom table.  See docs for WinCreateAtomTable(3).
1799*b39c5158Smillert
1800*b39c5158Smillert=item	DestroyAtomTable($atomtable)
1801*b39c5158Smillert
1802*b39c5158SmillertDispose of the table. (Version with prepended underscore returns 0 on success.)
1803*b39c5158Smillert
1804*b39c5158Smillert
1805*b39c5158Smillert=back
1806*b39c5158Smillert
1807*b39c5158Smillert=head2 Alerting the user
1808*b39c5158Smillert
1809*b39c5158Smillert=over
1810*b39c5158Smillert
1811*b39c5158Smillert=item Alarm([$type])
1812*b39c5158Smillert
1813*b39c5158SmillertAudible alarm of type $type (defaults to C<WA_ERROR=2>).  Other useful
1814*b39c5158Smillertvalues are C<WA_WARNING=0>, C<WA_NOTE=1>.  (What is C<WA_CDEFALARMS=3>???)
1815*b39c5158Smillert
1816*b39c5158SmillertThe duration and frequency of the alarms can be changed by the
1817*b39c5158SmillertOS2::SysValues_set(). The alarm frequency is defined to be in the range 0x0025
1818*b39c5158Smillertthrough 0x7FFF. The alarm is not generated if system value SV_ALARM is set
1819*b39c5158Smillertto FALSE. The alarms are dependent on the device capability.
1820*b39c5158Smillert
1821*b39c5158Smillert=item FlashWindow($hwnd, $doFlash)
1822*b39c5158Smillert
1823*b39c5158SmillertStarts/stops (depending on $doFlash being TRUE/FALSE) flashing the window
1824*b39c5158Smillert$hwnd's borders and titlebar.  First 5 flashes are accompanied by alarm beeps.
1825*b39c5158Smillert
1826*b39c5158SmillertExample (for VIO applications):
1827*b39c5158Smillert
1828*b39c5158Smillert  { my $morph = OS2::localMorphPM->new(0);
1829*b39c5158Smillert    print STDERR "Press ENTER!\n";
1830*b39c5158Smillert    FlashWindow(process_hwnd, 1);
1831*b39c5158Smillert    <>;
1832*b39c5158Smillert    FlashWindow(process_hwnd, 0);
1833*b39c5158Smillert  }
1834*b39c5158Smillert
1835*b39c5158SmillertSince flashing window persists even when application ends, it is very
1836*b39c5158Smillertimportant to protect the switching off flashing from non-local exits.  Use
1837*b39c5158Smillertthe class C<OS2::localFlashWindow> for this.  Creating the object of this
1838*b39c5158Smillertclass starts flashing the window until the object is destroyed.  The above
1839*b39c5158Smillertexample becomes:
1840*b39c5158Smillert
1841*b39c5158Smillert  print STDERR "Press ENTER!\n";
1842*b39c5158Smillert  { my $flash = OS2::localFlashWindow->new( process_hwnd );
1843*b39c5158Smillert    <>;
1844*b39c5158Smillert  }
1845*b39c5158Smillert
1846*b39c5158SmillertB<Notes from IBM docs:> Flashing a window brings the user's attention to a
1847*b39c5158Smillertwindow that is not the active window, where some important message or dialog
1848*b39c5158Smillertmust be seen by the user.
1849*b39c5158Smillert
1850*b39c5158SmillertNote:  It should be used only for important messages, for example, where some
1851*b39c5158Smillertcomponent of the system is failing and requires immediate attention to avoid
1852*b39c5158Smillertdamage.
1853*b39c5158Smillert
1854*b39c5158Smillert=item MessageBox($text, [ $title, [$flags, ...] ])
1855*b39c5158Smillert
1856*b39c5158SmillertShows a simple messagebox with (optional) icon, message $text, and one or
1857*b39c5158Smillertmore buttons to dismiss the box.  Returns the indicator of which action was
1858*b39c5158Smillerttaken by the user.  If optional argument $title is not given,
1859*b39c5158Smillertthe title is constructed from the application name.  The optional argument
1860*b39c5158Smillert$flags describes the appearance of the box; the default is to have B<Cancel>
1861*b39c5158Smillertbutton, I<INFO>-style icon, and a border for moving.  Flags should be
1862*b39c5158Smillerta combination of
1863*b39c5158Smillert
1864*b39c5158Smillert Buttons on the box: or Button Group
1865*b39c5158Smillert     MB_OK                 OK
1866*b39c5158Smillert     MB_OKCANCEL           both OK and CANCEL
1867*b39c5158Smillert     MB_CANCEL             CANCEL
1868*b39c5158Smillert     MB_ENTER              ENTER
1869*b39c5158Smillert     MB_ENTERCANCEL        both ENTER and CANCEL
1870*b39c5158Smillert     MB_RETRYCANCEL        both RETRY and CANCEL
1871*b39c5158Smillert     MB_ABORTRETRYIGNORE   ABORT, RETRY, and IGNORE
1872*b39c5158Smillert     MB_YESNO              both YES and NO
1873*b39c5158Smillert     MB_YESNOCANCEL        YES, NO, and CANCEL
1874*b39c5158Smillert
1875*b39c5158Smillert Color or Icon
1876*b39c5158Smillert     MB_ICONHAND           a small red circle with a red line across it.
1877*b39c5158Smillert     MB_ERROR              a small red circle with a red line across it.
1878*b39c5158Smillert     MB_ICONASTERISK       an information (i) icon.
1879*b39c5158Smillert     MB_INFORMATION        an information (i) icon.
1880*b39c5158Smillert     MB_ICONEXCLAMATION    an exclamation point (!) icon.
1881*b39c5158Smillert     MB_WARNING            an exclamation point (!) icon.
1882*b39c5158Smillert     MB_ICONQUESTION       a question mark (?) icon.
1883*b39c5158Smillert     MB_QUERY              a question mark (?) icon.
1884*b39c5158Smillert     MB_NOICON             No icon.
1885*b39c5158Smillert
1886*b39c5158Smillert Default action (i.e., focussed button; default is MB_DEFBUTTON1)
1887*b39c5158Smillert     MB_DEFBUTTON1         The first button is the default selection.
1888*b39c5158Smillert     MB_DEFBUTTON2         The second button is the default selection.
1889*b39c5158Smillert     MB_DEFBUTTON3         The third button is the default selection.
1890*b39c5158Smillert
1891*b39c5158Smillert Modality indicator
1892*b39c5158Smillert     MB_APPLMODAL                  Message box is application modal (default).
1893*b39c5158Smillert     MB_SYSTEMMODAL                Message box is system modal.
1894*b39c5158Smillert
1895*b39c5158Smillert Mobility indicator
1896*b39c5158Smillert     MB_MOVEABLE                   Message box is moveable.
1897*b39c5158Smillert
1898*b39c5158SmillertWith C<MB_MOVEABLE> the message box is displayed with a title bar and a
1899*b39c5158Smillertsystem menu, which shows only the Move, Close, and Task Manager choices,
1900*b39c5158Smillertwhich can be selected either by use of the pointing device or by
1901*b39c5158Smillertaccelerator keys.  If the user selects Close, the message box is removed
1902*b39c5158Smillertand the usResponse is set to C<MBID_CANCEL>, whether or not a cancel button
1903*b39c5158Smillertexisted within the message box.
1904*b39c5158Smillert
1905*b39c5158SmillertC<Esc> key dismisses the dialogue only if C<CANCEL> button is present; the
1906*b39c5158Smillertreturn value is C<MBID_CANCEL>.
1907*b39c5158Smillert
1908*b39c5158SmillertWith C<MB_APPLMODAL> the owner of the dialogue is disabled; therefore, do not
1909*b39c5158Smillertspecify the owner as the parent if this option is used.
1910*b39c5158Smillert
1911*b39c5158SmillertAdditionally, the following flag is possible, but probably not very useful:
1912*b39c5158Smillert
1913*b39c5158Smillert Help button
1914*b39c5158Smillert     MB_HELP             a HELP button appears, which sends a WM_HELP
1915*b39c5158Smillert				 message is sent to the window procedure of the
1916*b39c5158Smillert				 message box.
1917*b39c5158Smillert
1918*b39c5158SmillertOther optional arguments: $parent window, $owner_window, $helpID (used with
1919*b39c5158SmillertC<WM_HELP> message if C<MB_HELP> style is given).
1920*b39c5158Smillert
1921*b39c5158SmillertThe return value is one of
1922*b39c5158Smillert
1923*b39c5158Smillert  MBID_ENTER           ENTER was selected
1924*b39c5158Smillert  MBID_OK              OK was selected
1925*b39c5158Smillert  MBID_CANCEL          CANCEL was selected
1926*b39c5158Smillert  MBID_ABORT           ABORT was selected
1927*b39c5158Smillert  MBID_RETRY           RETRY was selected
1928*b39c5158Smillert  MBID_IGNORE          IGNORE was selected
1929*b39c5158Smillert  MBID_YES             YES was selected
1930*b39c5158Smillert  MBID_NO              NO was selected
1931*b39c5158Smillert
1932*b39c5158Smillert  0		           Function not successful; an error occurred.
1933*b39c5158Smillert
1934*b39c5158SmillertB<BUGS???> keyboard transversal by pressing C<TAB> key does not work.
1935*b39c5158SmillertDo not appear in window list, so may be hard to find if covered by other
1936*b39c5158Smillertwindows.
1937*b39c5158Smillert
1938*b39c5158Smillert=item _MessageBox($text, [ $title, [$flags, ...] ])
1939*b39c5158Smillert
1940*b39c5158SmillertSimilar to MessageBox(), but the default $title does not depend on the name
1941*b39c5158Smillertof the script.
1942*b39c5158Smillert
1943*b39c5158Smillert=item MessageBox2($text, [ $buttons_Icon, [$title, ...] ])
1944*b39c5158Smillert
1945*b39c5158SmillertSimilar to MessageBox(), but allows more flexible choice of button texts
1946*b39c5158Smillertand the icon. $buttons_Icon is a reference to an array with information about
1947*b39c5158Smillertbuttons and the icon to use; the semantic of this array is the same as
1948*b39c5158Smillertfor argument list of process_MB2_INFO().  The default value will show
1949*b39c5158Smillertone button B<Dismiss> which will return C<0x1000>.
1950*b39c5158Smillert
1951*b39c5158SmillertOther optional arguments are the same as for MessageBox().
1952*b39c5158Smillert
1953*b39c5158SmillertB<NOTE.> Remark about C<MBID_CANCEL> in presence of C<MB_MOVABLE> is
1954*b39c5158Smillertequally applicable to MessageBox() and MessageBox2().
1955*b39c5158Smillert
1956*b39c5158SmillertExample:
1957*b39c5158Smillert
1958*b39c5158Smillert  print MessageBox2
1959*b39c5158Smillert    'Foo prints 100, Bar 101, Baz 102',
1960*b39c5158Smillert    [['~Foo' => 100, 'B~ar' => 101, ['Ba~z'] => 102]],
1961*b39c5158Smillert    'Choose a number to print';
1962*b39c5158Smillert
1963*b39c5158Smillertwill show a messagebox with
1964*b39c5158Smillert
1965*b39c5158Smillert=over 20
1966*b39c5158Smillert
1967*b39c5158Smillert=item Title
1968*b39c5158Smillert
1969*b39c5158SmillertB<Choose a number to print>,
1970*b39c5158Smillert
1971*b39c5158Smillert=item Text
1972*b39c5158Smillert
1973*b39c5158SmillertB<Foo prints 100, Bar 101, Baz 102>
1974*b39c5158Smillert
1975*b39c5158Smillert=item Icon
1976*b39c5158Smillert
1977*b39c5158SmillertINFORMATION ICON
1978*b39c5158Smillert
1979*b39c5158Smillert=item Buttons
1980*b39c5158Smillert
1981*b39c5158SmillertB<Foo>, B<Bar>, B<Baz>
1982*b39c5158Smillert
1983*b39c5158Smillert=item Default button
1984*b39c5158Smillert
1985*b39c5158SmillertB<Baz>
1986*b39c5158Smillert
1987*b39c5158Smillert=item accelerator keys
1988*b39c5158Smillert
1989*b39c5158SmillertB<F>, B<a>, and B<z>
1990*b39c5158Smillert
1991*b39c5158Smillert=item return values
1992*b39c5158Smillert
1993*b39c5158Smillert100, 101, and 102 correspondingly,
1994*b39c5158Smillert
1995*b39c5158Smillert=back
1996*b39c5158Smillert
1997*b39c5158SmillertUsing
1998*b39c5158Smillert
1999*b39c5158Smillert  print MessageBox2
2000*b39c5158Smillert    'Foo prints 100, Bar 101, Baz 102',
2001*b39c5158Smillert    [['~Foo' => 100, 'B~ar' => 101, ['Ba~z'] => 102], 'SP#22'],
2002*b39c5158Smillert    'Choose a number to print';
2003*b39c5158Smillert
2004*b39c5158Smillertwill show the 22nd system icon as the dialog icon (small folder icon).
2005*b39c5158Smillert
2006*b39c5158Smillert=item _MessageBox2($text, $buttons_Icon_struct, [$title, ...])
2007*b39c5158Smillert
2008*b39c5158Smillertlow-level workhorse to implement MessageBox2().  Differs by the dafault
2009*b39c5158Smillert$title, and that $buttons_Icon_struct is required, and is a string with
2010*b39c5158Smillertlow-level C struct.
2011*b39c5158Smillert
2012*b39c5158Smillert=item process_MB2_INFO($buttons, [$iconID, [$flags, [$notifyWindow]]])
2013*b39c5158Smillert
2014*b39c5158Smillertlow-level workhorse to implement MessageBox2(); calculates the second
2015*b39c5158Smillertargument of _MessageBox2().  $buttons is a reference
2016*b39c5158Smillertto array of button descriptions.  $iconID is either an ID of icon for
2017*b39c5158Smillertthe message box, or a string of the form C<"SP#number">; in the latter case
2018*b39c5158Smillertthe number's system icon is chosen; this field is ignored unless
2019*b39c5158Smillert$flags contains C<MB_CUSTOMICON> flag.  $flags has the same meaning as mobility,
2020*b39c5158Smillertmodality, and icon flags for MessageBox() with addition of extra flags
2021*b39c5158Smillert
2022*b39c5158Smillert     MB_CUSTOMICON         Use a custom icon specified in hIcon.
2023*b39c5158Smillert     MB_NONMODAL           Message box is nonmodal
2024*b39c5158Smillert
2025*b39c5158Smillert$flags defaults to C<MB_INFORMATION> or C<MB_CUSTOMICON> (depending on whether
2026*b39c5158Smillert$iconID is non-0), combined with MB_MOVABLE.
2027*b39c5158Smillert
2028*b39c5158SmillertEach button's description takes two elements of the description array,
2029*b39c5158Smillertappearance description, and the return value of MessageBox2() if this
2030*b39c5158Smillertbutton is selected.  The appearance description is either an array reference
2031*b39c5158Smillertof the form C<[$button_Text, $button_Style]>, or the same without
2032*b39c5158Smillert$button_Style (then style is C<BS_DEFAULT>, making this button the default)
2033*b39c5158Smillertor just $button_Text (with "normal" style).  E.g., the list
2034*b39c5158Smillert
2035*b39c5158Smillert  Foo => 100, Bar => 101, [Baz] => 102
2036*b39c5158Smillert
2037*b39c5158Smillertwill show three buttons B<Foo>, B<Bar>, B<Baz> with B<Baz> being the default
2038*b39c5158Smillertbutton; pressing buttons return 100, 101, or 102 correspondingly.
2039*b39c5158Smillert
2040*b39c5158SmillertIn particular, exactly one button should have C<BS_DEFAULT> style (e.g.,
2041*b39c5158Smillertgiven as C<[$button_Name]>); otherwise the message box will not have keyboard
2042*b39c5158Smillertfocus!  (The only exception is the case of one button; then C<[$button_Name]>
2043*b39c5158Smillertcan be replaced (for convenience) with plain C<$button_Name>.)
2044*b39c5158Smillert
2045*b39c5158SmillertIf text of the button contains character C<~>, the following character becomes
2046*b39c5158Smillertthe keyboard accelerator for this button.  One can also get the handle
2047*b39c5158Smillertof system icons directly, so C<'SP#22'> can be replaced by
2048*b39c5158SmillertC<OS2::Process::get_pointer(22)>; see also C<SPTR_*> constants.
2049*b39c5158Smillert
2050*b39c5158SmillertB<NOTE> With C<MB_NONMODAL> the program continues after displaying the
2051*b39c5158Smillertnonmodal message box.  The message box remains visible until the owner window
2052*b39c5158Smillertdestroys it. Two notification messages, WM_MSGBOXINIT and WM_MSGBOXDISMISS,
2053*b39c5158Smillertare used to support this non-modality.
2054*b39c5158Smillert
2055*b39c5158Smillert=item LoadPointer($id, [$module, [$hwnd]])
2056*b39c5158Smillert
2057*b39c5158SmillertLoads a handle for the pointer $id from the resources of the module
2058*b39c5158Smillert$module on desktop $hwnd.  If $module is 0 (default), loads from the main
2059*b39c5158Smillertexecutable; otherwise from a DLL with the handle $module.
2060*b39c5158Smillert
2061*b39c5158SmillertThe pointer is owned by the process, and is destroyed by
2062*b39c5158SmillertDestroyPointer() call, or when the process terminates.
2063*b39c5158Smillert
2064*b39c5158Smillert=item SysPointer($id, [$copy, [$hwnd]])
2065*b39c5158Smillert
2066*b39c5158SmillertGets a handle for (a copy of) the system pointer $id (the value should
2067*b39c5158Smillertbe one of C<SPTR_*> constants).  A copy is made if $copy is TRUE (the
2068*b39c5158Smillertdefault).  $hwnd defaults to C<HWND_DESKTOP>.
2069*b39c5158Smillert
2070*b39c5158Smillert=item get_pointer($id, [$copy, [$hwnd]])
2071*b39c5158Smillert
2072*b39c5158SmillertGets (and caches) a copy of the system pointer.
2073*b39c5158Smillert
2074*b39c5158Smillert=back
2075*b39c5158Smillert
2076*b39c5158Smillert=head2 Constants used by OS/2 APIs
2077*b39c5158Smillert
2078*b39c5158SmillertFunction C<os2constant($name)> returns the value of the constant; to
2079*b39c5158Smillertdecrease the memory usage of this package, only the constants used by
2080*b39c5158SmillertAPIs called by Perl functions in this package are made available.
2081*b39c5158Smillert
2082*b39c5158SmillertFor direct access, see also the L<"EXPORTS"> section; the latter way
2083*b39c5158Smillertmay also provide some performance advantages, since the value of the
2084*b39c5158Smillertconstant is cached.
2085*b39c5158Smillert
2086*b39c5158Smillert=head1 L<OS2::localMorphPM>, OS2::localFlashWindow, and OS2::localClipbrd classes
2087*b39c5158Smillert
2088*b39c5158SmillertThe class C<OS2::localMorphPM> morphs the process to PM for the duration of
2089*b39c5158Smillertthe given scope.
2090*b39c5158Smillert
2091*b39c5158Smillert  {
2092*b39c5158Smillert    my $h = OS2::localMorphPM->new(0);
2093*b39c5158Smillert    # Do something
2094*b39c5158Smillert  }
2095*b39c5158Smillert
2096*b39c5158SmillertThe argument has the same meaning as one to OS2::MorphPM().  Calls can
2097*b39c5158Smillertnest with internal ones being NOPs.
2098*b39c5158Smillert
2099*b39c5158SmillertLikewise, C<OS2::localClipbrd> class opens the clipboard for the duration
2100*b39c5158Smillertof the current scope; if TRUE optional argument is given, it would not
2101*b39c5158Smillertmorph the application into PM:
2102*b39c5158Smillert
2103*b39c5158Smillert  {
2104*b39c5158Smillert    my $handle = OS2::localClipbrd->new(1);	# Do not morph into PM
2105*b39c5158Smillert    # Do something with clipboard here...
2106*b39c5158Smillert  }
2107*b39c5158Smillert
2108*b39c5158SmillertC<OS2::localFlashWindow> behaves similarly; see
2109*b39c5158SmillertL<FlashWindow($hwnd, $doFlash)>.
2110*b39c5158Smillert
2111*b39c5158Smillert=head1 EXAMPLES
2112*b39c5158Smillert
2113*b39c5158SmillertThe test suite for this module contains an almost comprehensive collection
2114*b39c5158Smillertof examples of using the API of this module.
2115*b39c5158Smillert
2116*b39c5158Smillert=head1 TODO
2117*b39c5158Smillert
2118*b39c5158SmillertAdd tests for:
2119*b39c5158Smillert
2120*b39c5158Smillert	SwitchToProgram
2121*b39c5158Smillert	ClassName
2122*b39c5158Smillert	out_codepage
2123*b39c5158Smillert	out_codepage_set
2124*b39c5158Smillert	in_codepage
2125*b39c5158Smillert	in_codepage_set
2126*b39c5158Smillert	cursor
2127*b39c5158Smillert	cursor_set
2128*b39c5158Smillert	screen
2129*b39c5158Smillert	screen_set
2130*b39c5158Smillert	process_codepages
2131*b39c5158Smillert	QueryWindow
2132*b39c5158Smillert	EnumDlgItem
2133*b39c5158Smillert        WindowPtr
2134*b39c5158Smillert        WindowUShort
2135*b39c5158Smillert        SetWindowBits
2136*b39c5158Smillert        SetWindowPtr
2137*b39c5158Smillert        SetWindowULong
2138*b39c5158Smillert        SetWindowUShort
2139*b39c5158Smillert	my_type
2140*b39c5158Smillert	file_type
2141*b39c5158Smillert	scrsize
2142*b39c5158Smillert	scrsize_set
2143*b39c5158Smillert
2144*b39c5158SmillertDocument: InvalidateRect,
2145*b39c5158SmillertCreateFrameControls, kbdChar, kbdhChar,
2146*b39c5158SmillertkbdStatus, _kbdStatus_set, kbdhStatus, kbdhStatus_set,
2147*b39c5158SmillertvioConfig, viohConfig, vioMode, viohMode, viohMode_set, _vioMode_set,
2148*b39c5158Smillert_vioState, _vioState_set, vioFont, vioFont_set
2149*b39c5158Smillert
2150*b39c5158SmillertTest: SetWindowULong/Short/Ptr, SetWindowBits. InvalidateRect,
2151*b39c5158SmillertCreateFrameControls, ClipbrdOwner_set, ClipbrdViewer_set, _ClipbrdData_set,
2152*b39c5158SmillertAlarm, FlashWindow, _MessageBox, MessageBox, _MessageBox2, MessageBox2,
2153*b39c5158SmillertLoadPointer, SysPointer, kbdChar, kbdhChar, kbdStatus, _kbdStatus_set,
2154*b39c5158SmillertkbdhStatus,  kbdhStatus_set, vioConfig, viohConfig, vioMode, viohMode,
2155*b39c5158SmillertviohMode_set, _vioMode_set, _vioState, _vioState_set, vioFont, vioFont_set
2156*b39c5158Smillert
2157*b39c5158SmillertImplement SOMETHINGFROMMR.
2158*b39c5158Smillert
2159*b39c5158Smillert
2160*b39c5158Smillert  >But I wish to change the default button if the user enters some
2161*b39c5158Smillert  >text into an entryfield.  I can detect the entry ok, but can't
2162*b39c5158Smillert  >seem to get the button to change to default.
2163*b39c5158Smillert  >
2164*b39c5158Smillert  >No matter what message I send it, it's being ignored.
2165*b39c5158Smillert
2166*b39c5158Smillert  You need to get the style of the buttons using WinQueryWindowULong/QWL_STYLE,
2167*b39c5158Smillert  set and reset the BS_DEFAULT bits as appropriate and then use
2168*b39c5158Smillert  WinSetWindowULong/QWL_STYLE to set the button style.
2169*b39c5158Smillert  Something like this:
2170*b39c5158Smillert    hwnd1 = WinWindowFromID (hwnd, id1);
2171*b39c5158Smillert    hwnd2 = WinWindowFromID (hwnd, id2);
2172*b39c5158Smillert    style1 = WinQueryWindowULong (hwnd1, QWL_STYLE);
2173*b39c5158Smillert    style2 = WinQueryWindowULong (hwnd2, QWL_STYLE);
2174*b39c5158Smillert    style1 |= style2 & BS_DEFAULT;
2175*b39c5158Smillert    style2 &= ~BS_DEFAULT;
2176*b39c5158Smillert    WinSetWindowULong (hwnd1, QWL_STYLE, style1);
2177*b39c5158Smillert    WinSetWindowULong (hwnd2, QWL_STYLE, style2);
2178*b39c5158Smillert
2179*b39c5158Smillert > How to do query and change a frame creation flags for existing window?
2180*b39c5158Smillert
2181*b39c5158Smillert Set the style bits that correspond to the FCF_* flag for the frame
2182*b39c5158Smillert window and then send a WM_UPDATEFRAME message with the appropriate FCF_*
2183*b39c5158Smillert flag in mp1.
2184*b39c5158Smillert
2185*b39c5158Smillert ULONG ulFrameStyle;
2186*b39c5158Smillert ulFrameStyle = WinQueryWindowULong( WinQueryWindow(hwnd, QW_PARENT),
2187*b39c5158Smillert QWL_STYLE );
2188*b39c5158Smillert ulFrameStyle = (ulFrameStyle & ~FS_SIZEBORDER) | FS_BORDER;
2189*b39c5158Smillert WinSetWindowULong(   WinQueryWindow(hwnd, QW_PARENT),
2190*b39c5158Smillert                      QWL_STYLE,
2191*b39c5158Smillert                      ulFrameStyle );
2192*b39c5158Smillert WinSendMsg( WinQueryWindow(hwnd, QW_PARENT),
2193*b39c5158Smillert             WM_UPDATEFRAME,
2194*b39c5158Smillert             MPFROMP(FCF_SIZEBORDER),
2195*b39c5158Smillert             MPVOID );
2196*b39c5158Smillert
2197*b39c5158Smillert If the FCF_* flags you want to change does not have a corresponding FS_*
2198*b39c5158Smillert style (i.e. the FCF_* flag corresponds to the presence/lack of a frame
2199*b39c5158Smillert control rather than a property of the frame itself) then you create or
2200*b39c5158Smillert destroy the appropriate control window using the correct FID_* window
2201*b39c5158Smillert identifier and then send the WM_UPDATEFRAME message with the appropriate
2202*b39c5158Smillert FCF_* flag in mp1.
2203*b39c5158Smillert
2204*b39c5158Smillert /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
2205*b39c5158Smillert  |  SetFrameBorder()                                                          |
2206*b39c5158Smillert  |    Changes a frame window's border to the requested type.                  |
2207*b39c5158Smillert  |                                                                            |
2208*b39c5158Smillert  |  Parameters on entry:                                                      |
2209*b39c5158Smillert  |    hwndFrame     -> Frame window whose border is to be changed.            |
2210*b39c5158Smillert  |    ulBorderStyle -> Type of border to change to.                           |
2211*b39c5158Smillert  |                                                                            |
2212*b39c5158Smillert  |  Returns:                                                                  |
2213*b39c5158Smillert  |    BOOL          -> Success indicator.                                     |
2214*b39c5158Smillert  |                                                                            |
2215*b39c5158Smillert  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
2216*b39c5158Smillert BOOL SetFrameBorder( HWND hwndFrame, ULONG ulBorderType )  {
2217*b39c5158Smillert   ULONG  ulFrameStyle;
2218*b39c5158Smillert   BOOL   fSuccess = TRUE;
2219*b39c5158Smillert
2220*b39c5158Smillert   ulFrameStyle = WinQueryWindowULong( hwndFrame, QWL_STYLE );
2221*b39c5158Smillert
2222*b39c5158Smillert   switch ( ulBorderType )  {
2223*b39c5158Smillert     case FS_SIZEBORDER :
2224*b39c5158Smillert       ulFrameStyle = (ulFrameStyle & ~(FS_DLGBORDER | FS_BORDER))
2225*b39c5158Smillert                      | FS_SIZEBORDER;
2226*b39c5158Smillert       break;
2227*b39c5158Smillert
2228*b39c5158Smillert     case FS_DLGBORDER :
2229*b39c5158Smillert       ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_BORDER))
2230*b39c5158Smillert                      | FS_DLGBORDER;
2231*b39c5158Smillert       break;
2232*b39c5158Smillert
2233*b39c5158Smillert     case FS_BORDER :
2234*b39c5158Smillert       ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_DLGBORDER))
2235*b39c5158Smillert                      | FS_BORDER;
2236*b39c5158Smillert       break;
2237*b39c5158Smillert
2238*b39c5158Smillert     default :
2239*b39c5158Smillert       fSuccess = FALSE;
2240*b39c5158Smillert       break;
2241*b39c5158Smillert   }  // end switch
2242*b39c5158Smillert
2243*b39c5158Smillert   if ( fSuccess )  {
2244*b39c5158Smillert     fSuccess = WinSetWindowULong( hwndFrame, QWL_STYLE, ulFrameStyle );
2245*b39c5158Smillert
2246*b39c5158Smillert     if ( fSuccess )  {
2247*b39c5158Smillert       fSuccess = (BOOL)WinSendMsg( hwndFrame, WM_UPDATEFRAME, 0, 0 );
2248*b39c5158Smillert       if ( fSuccess )
2249*b39c5158Smillert         fSuccess = WinInvalidateRect( hwndFrame, NULL, TRUE );
2250*b39c5158Smillert     }
2251*b39c5158Smillert   }
2252*b39c5158Smillert
2253*b39c5158Smillert   return ( fSuccess );
2254*b39c5158Smillert
2255*b39c5158Smillert }  // End SetFrameBorder()
2256*b39c5158Smillert
2257*b39c5158Smillert         hwndMenu=WinLoadMenu(hwndParent,NULL,WND_IMAGE);
2258*b39c5158Smillert         WinSetWindowUShort(hwndMenu,QWS_ID,FID_MENU);
2259*b39c5158Smillert         ulStyle=WinQueryWindowULong(hwndMenu,QWL_STYLE);
2260*b39c5158Smillert         WinSetWindowULong(hwndMenu,QWL_STYLE,ulStyle|MS_ACTIONBAR);
2261*b39c5158Smillert         WinSendMsg(hwndParent,WM_UPDATEFRAME,MPFROMSHORT(FCF_MENU),0L);
2262*b39c5158Smillert
2263*b39c5158Smillert  OS/2-windows have another "parent" called the *owner*,
2264*b39c5158Smillert  which must be set separately - to get a close relationship:
2265*b39c5158Smillert
2266*b39c5158Smillert    WinSetOwner (hwndFrameChild, hwndFrameMain);
2267*b39c5158Smillert
2268*b39c5158Smillert  Now your child should move with your main window!
2269*b39c5158Smillert  And always stays on top of it....
2270*b39c5158Smillert
2271*b39c5158Smillert  To avoid this, for example for dialogwindows, you can
2272*b39c5158Smillert  also "disconnect" this relationship with:
2273*b39c5158Smillert
2274*b39c5158Smillert    WinSetWindowBits (hwndFrameChild, QWL_STYLE
2275*b39c5158Smillert                      , FS_NOMOVEWITHOWNER
2276*b39c5158Smillert                      , FS_NOMOVEWITHOWNER);
2277*b39c5158Smillert
2278*b39c5158Smillert Adding a button icon later:
2279*b39c5158Smillert
2280*b39c5158Smillert /* switch the button style to BS_MINIICON */
2281*b39c5158Smillert WinSetWindowBits(hwndBtn, QWL_STYLE, BS_MINIICON, BS_MINIICON) ;
2282*b39c5158Smillert
2283*b39c5158Smillert /* set up button control data */
2284*b39c5158Smillert BTNCDATA    bcd;
2285*b39c5158Smillert bcd.cb = sizeof(BTNCDATA);
2286*b39c5158Smillert bcd.hImage = WinLoadPointer(HWND_DESKTOP, dllHandle, ID_ICON_BUTTON1) ;
2287*b39c5158Smillert bcd.fsCheckState = bcd.fsHiliteState = 0 ;
2288*b39c5158Smillert
2289*b39c5158Smillert
2290*b39c5158Smillert WNDPARAMS   wp;
2291*b39c5158Smillert wp.fsStatus = WPM_CTLDATA;
2292*b39c5158Smillert wp.pCtlData = &bcd;
2293*b39c5158Smillert
2294*b39c5158Smillert /* add the icon on the button */
2295*b39c5158Smillert WinSendMsg(hwndBtn, WM_SETWINDOWPARAMS, (MPARAM)&wp, NULL);
2296*b39c5158Smillert
2297*b39c5158Smillert MO> Can anyone tell what OS/2 expects of an application to be properly
2298*b39c5158Smillert MO> minimized to the desktop?
2299*b39c5158Smillert case WM MINMAXFRAME :
2300*b39c5158Smillert {
2301*b39c5158Smillert   BOOL  fShow = ! (((PSWP) mp1)->fl & SWP MINIMIZE);
2302*b39c5158Smillert   HENUM henum;
2303*b39c5158Smillert
2304*b39c5158Smillert   HWND  hwndChild;
2305*b39c5158Smillert
2306*b39c5158Smillert   WinEnableWindowUpdate ( hwnd, FALSE );
2307*b39c5158Smillert
2308*b39c5158Smillert   for (henum=WinBeginEnumWindows(hwnd);
2309*b39c5158Smillert        (hwndChild = WinGetNextWindow (henum)) != 0; )
2310*b39c5158Smillert   WinShowWindow ( hwndChild, fShow );
2311*b39c5158Smillert
2312*b39c5158Smillert   WinEndEnumWindows ( henum );
2313*b39c5158Smillert   WinEnableWindowUpdate ( hwnd, TRUE );
2314*b39c5158Smillert }
2315*b39c5158Smillert break;
2316*b39c5158Smillert
2317*b39c5158SmillertWhy C<hWindowPos DesktopWindow> gives C<< behind => HWND_TOP >>?
2318*b39c5158Smillert
2319*b39c5158Smillert=head1 $^E
2320*b39c5158Smillert
2321*b39c5158Smillertthe majority of the APIs of this module set $^E on failure (no matter
2322*b39c5158Smillertwhether they die() on failure or not).  By the semantic of PM API
2323*b39c5158Smillertwhich returns something other than a boolean, it is impossible to
2324*b39c5158Smillertdistinguish failure from a "normal" 0-return.  In such cases C<$^E ==
2325*b39c5158Smillert0> indicates an absence of error.
2326*b39c5158Smillert
2327*b39c5158Smillert=head1 EXPORTS
2328*b39c5158Smillert
2329*b39c5158SmillertIn addition to symbols described above, the following constants (available
2330*b39c5158Smillertalso via module C<OS2::Process::Const>) are exportable.  Note that these
2331*b39c5158Smillertsymbols live in package C<OS2::Process::Const>, they are not available
2332*b39c5158Smillertby full name through C<OS2::Process>!
2333*b39c5158Smillert
2334*b39c5158Smillert  HWND_*		Standard (abstract) window handles
2335*b39c5158Smillert  WM_*			Message ids
2336*b39c5158Smillert  SC_*			WM_SYSCOMMAND flavor
2337*b39c5158Smillert  SWP_*			Size/move etc flag
2338*b39c5158Smillert  WC_*			Standard window classes
2339*b39c5158Smillert  PROG_*		Program category (PM, VIO etc)
2340*b39c5158Smillert  QW_*			Query-Window flag
2341*b39c5158Smillert  EDI_*			Enumerate-Dialog-Item code
2342*b39c5158Smillert  WS_*			Window Style flag
2343*b39c5158Smillert  QWS_*			Query-window-UShort offsets
2344*b39c5158Smillert  QWP_*			Query-window-pointer offsets
2345*b39c5158Smillert  QWL_*			Query-window-ULong offsets
2346*b39c5158Smillert  FF_*			Frame-window state flags
2347*b39c5158Smillert  FI_*			Frame-window information flags
2348*b39c5158Smillert  LS_*			List box styles
2349*b39c5158Smillert  FS_*			Frame style
2350*b39c5158Smillert  FCF_*			Frame creation flags
2351*b39c5158Smillert  BS_*			Button style
2352*b39c5158Smillert  MS_*			Menu style
2353*b39c5158Smillert  TBM_*			Title bar messages?
2354*b39c5158Smillert  CF_*			Clipboard formats
2355*b39c5158Smillert  CFI_*			Clipboard storage type
2356*b39c5158Smillert  FID_*			ids of subwindows of frames
2357*b39c5158Smillert
2358*b39c5158Smillert=head1 BUGS
2359*b39c5158Smillert
2360*b39c5158Smillertwhether a given API dies or returns FALSE/empty-list on error may be
2361*b39c5158Smillertconfusing.  This may change in the future.
2362*b39c5158Smillert
2363*b39c5158Smillert=head1 AUTHOR
2364*b39c5158Smillert
2365*b39c5158SmillertAndreas Kaiser <ak@ananke.s.bawue.de>,
2366*b39c5158SmillertIlya Zakharevich <ilya@math.ohio-state.edu>.
2367*b39c5158Smillert
2368*b39c5158Smillert=head1 SEE ALSO
2369*b39c5158Smillert
2370*b39c5158SmillertC<spawn*>() system calls, L<OS2::Proc> and L<OS2::WinObject> modules.
2371*b39c5158Smillert
2372*b39c5158Smillert=cut
2373