1package OS2::localMorphPM;
2# use strict;
3
4sub new {
5  my ($c,$f) = @_;
6  OS2::MorphPM($f);
7  # print STDERR ">>>>>\n";
8  bless [$f], $c
9}
10sub DESTROY {
11  # print STDERR "<<<<<\n";
12  OS2::UnMorphPM(shift->[0])
13}
14
15package OS2::Process;
16
17BEGIN {
18  require Exporter;
19  require XSLoader;
20  #require AutoLoader;
21
22  our @ISA = qw(Exporter);
23  our $VERSION = "1.02";
24  XSLoader::load('OS2::Process', $VERSION);
25}
26
27# Items to export into callers namespace by default. Note: do not export
28# names by default without a very good reason. Use EXPORT_OK instead.
29# Do not simply export all your public functions/methods/constants.
30our @EXPORT = qw(
31	P_BACKGROUND
32	P_DEBUG
33	P_DEFAULT
34	P_DETACH
35	P_FOREGROUND
36	P_FULLSCREEN
37	P_MAXIMIZE
38	P_MINIMIZE
39	P_NOCLOSE
40	P_NOSESSION
41	P_NOWAIT
42	P_OVERLAY
43	P_PM
44	P_QUOTE
45	P_SESSION
46	P_TILDE
47	P_UNRELATED
48	P_WAIT
49	P_WINDOWED
50	my_type
51	file_type
52	T_NOTSPEC
53	T_NOTWINDOWCOMPAT
54	T_WINDOWCOMPAT
55	T_WINDOWAPI
56	T_BOUND
57	T_DLL
58	T_DOS
59	T_PHYSDRV
60	T_VIRTDRV
61	T_PROTDLL
62	T_32BIT
63	ppid
64	ppidOf
65	sidOf
66	scrsize
67	scrsize_set
68	kbdChar
69	kbdhChar
70	kbdStatus
71	_kbdStatus_set
72	kbdhStatus
73	kbdhStatus_set
74	vioConfig
75	viohConfig
76	vioMode
77	viohMode
78	viohMode_set
79	_vioMode_set
80	_vioState
81	_vioState_set
82	vioFont
83	vioFont_set
84	process_entry
85	process_entries
86	process_hentry
87	process_hentries
88	change_entry
89	change_entryh
90	process_hwnd
91	Title_set
92	Title
93	winTitle_set
94	winTitle
95	swTitle_set
96	bothTitle_set
97	WindowText
98	WindowText_set
99	WindowPos
100	WindowPos_set
101	hWindowPos
102	hWindowPos_set
103	WindowProcess
104	SwitchToProgram
105	DesktopWindow
106	ActiveWindow
107	ActiveWindow_set
108	ClassName
109	FocusWindow
110	FocusWindow_set
111	ShowWindow
112	PostMsg
113	BeginEnumWindows
114	EndEnumWindows
115	GetNextWindow
116	IsWindow
117	ChildWindows
118	out_codepage
119	out_codepage_set
120	process_codepage_set
121	in_codepage
122	in_codepage_set
123	cursor
124	cursor_set
125	screen
126	screen_set
127	process_codepages
128	QueryWindow
129	WindowFromId
130	WindowFromPoint
131	EnumDlgItem
132        EnableWindow
133        EnableWindowUpdate
134        IsWindowEnabled
135        IsWindowVisible
136        IsWindowShowing
137        WindowPtr
138        WindowULong
139        WindowUShort
140        SetWindowBits
141        SetWindowPtr
142        SetWindowULong
143        SetWindowUShort
144	TopLevel
145	FocusWindow_set_keep_Zorder
146
147	ActiveDesktopPathname
148	InvalidateRect
149	CreateFrameControl
150	ClipbrdFmtInfo
151	ClipbrdOwner
152	ClipbrdViewer
153	ClipbrdData
154	OpenClipbrd
155	CloseClipbrd
156	ClipbrdData_set
157	ClipbrdOwner_set
158	ClipbrdViewer_set
159	EnumClipbrdFmts
160	EmptyClipbrd
161	AddAtom
162	FindAtom
163	DeleteAtom
164	AtomUsage
165	AtomName
166	AtomLength
167	SystemAtomTable
168	CreateAtomTable
169	DestroyAtomTable
170
171	_ClipbrdData_set
172	ClipbrdText
173	ClipbrdText_set
174
175	_MessageBox
176	MessageBox
177	_MessageBox2
178	MessageBox2
179	LoadPointer
180	SysPointer
181	Alarm
182	FlashWindow
183
184	get_title
185	set_title
186);
187our @EXPORT_OK = qw(
188	ResetWinError
189        MPFROMSHORT
190        MPVOID
191        MPFROMCHAR
192        MPFROM2SHORT
193        MPFROMSH2CH
194        MPFROMLONG
195);
196
197our $AUTOLOAD;
198
199sub AUTOLOAD {
200    # This AUTOLOAD is used to 'autoload' constants from the constant()
201    # XS function.  If a constant is not found then control is passed
202    # to the AUTOLOAD in AutoLoader.
203
204    (my $constname = $AUTOLOAD) =~ s/.*:://;
205    my $val = constant($constname, @_ ? $_[0] : 0);
206    if ($! != 0) {
207	if ($! =~ /Invalid/ || $!{EINVAL}) {
208	    die "Unsupported function $AUTOLOAD"
209	} else {
210	    my ($pack,$file,$line) = caller;
211	    die "Your vendor has not defined OS2::Process macro $constname, used at $file line $line.
212";
213	}
214    }
215    eval "sub $AUTOLOAD { $val }";
216    goto &$AUTOLOAD;
217}
218
219sub const_import {
220  require OS2::Process::Const;
221  my $sym = shift;
222  my ($err, $val) = OS2::Process::Const::constant($sym);
223  die $err if $err;
224  my $p = caller(1);
225
226  # no strict;
227
228  *{"$p\::$sym"} = sub () { $val };
229  ();			# needed by import()
230}
231
232sub import {
233  my $class = shift;
234  my $ini = @_;
235  @_ = ($class,
236	map {
237	  /^(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($_) : $_
238	} @_);
239  goto &Exporter::import if @_ > 1 or $ini == 0;
240}
241
242# Preloaded methods go here.
243
244sub Title () { (process_entry())[0] }
245
246# *Title_set = \&sesmgr_title_set;
247
248sub swTitle_set_sw {
249  my ($title, @sw) = @_;
250  $sw[0] = $title;
251  change_entry(@sw);
252}
253
254sub swTitle_set ($) {
255  my (@sw) = process_entry();
256  swTitle_set_sw(shift, @sw);
257}
258
259sub winTitle_set_sw {
260  my ($title, @sw) = @_;
261  my $h = OS2::localMorphPM->new(0);
262  WindowText_set $sw[1], $title;
263}
264
265sub winTitle_set ($) {
266  my (@sw) = process_entry();
267  winTitle_set_sw(shift, @sw);
268}
269
270sub winTitle () {
271  my (@sw) = process_entry();
272  my $h = OS2::localMorphPM->new(0);
273  WindowText $sw[1];
274}
275
276sub bothTitle_set ($) {
277  my (@sw) = process_entry();
278  my $t = shift;
279  winTitle_set_sw($t, @sw);
280  swTitle_set_sw($t, @sw);
281}
282
283sub Title_set ($) {
284  my $t = shift;
285  return 1 if sesmgr_title_set($t);
286  return 0 unless $^E == 372;
287  my (@sw) = process_entry();
288  winTitle_set_sw($t, @sw);
289  swTitle_set_sw($t, @sw);
290}
291
292sub process_entry { swentry_expand(process_swentry(@_)) }
293
294our @hentry_fields = qw( title owner_hwnd icon_hwnd
295			 owner_phandle owner_pid owner_sid
296			 visible nonswitchable jumpable ptype sw_entry );
297
298sub swentry_hexpand ($) {
299  my %h;
300  @h{@hentry_fields} = swentry_expand(shift);
301  \%h;
302}
303
304sub process_hentry { swentry_hexpand(process_swentry(@_)) }
305sub process_hwnd { process_hentry()->{owner_hwnd} }
306
307my $swentry_size = swentry_size();
308
309sub sw_entries () {
310  my $s = swentries_list();
311  my ($c, $s1) = unpack 'La*', $s;
312  die "Unconsistent size in swentries_list()" unless 4+$c*$swentry_size == length $s;
313  my (@l, $e);
314  push @l, $e while $e = substr $s1, 0, $swentry_size, '';
315  @l;
316}
317
318sub process_entries () {
319  map [swentry_expand($_)], sw_entries;
320}
321
322sub process_hentries () {
323  map swentry_hexpand($_), sw_entries;
324}
325
326sub change_entry {
327  change_swentry(create_swentry(@_));
328}
329
330sub create_swentryh ($) {
331  my $h = shift;
332  create_swentry(@$h{@hentry_fields});
333}
334
335sub change_entryh ($) {
336  change_swentry(create_swentryh(shift));
337}
338
339# Massage entries into the same order as WindowPos_set:
340sub WindowPos ($) {
341  my ($fl, $h, $w, $y, $x, $behind, $hwnd, @rest)
342	= unpack 'L l4 L4', WindowSWP(shift);
343  ($x, $y, $fl, $w, $h, $behind, @rest);
344}
345
346# Put them into a hash
347sub hWindowPos ($) {
348  my %h;
349  @h{ qw(flags height width y x behind hwnd reserved1 reserved2) }
350	= unpack 'L l4 L4', WindowSWP(shift);
351  \%h;
352}
353
354my @SWP_keys = ( [qw(width height)],	# SWP_SIZE=1
355		 [qw(x y)],		# SWP_MOVE=2
356		 [qw(behind)] );	# SWP_ZORDER=3
357my %SWP_def;
358@SWP_def{ map @$_, @SWP_keys }  = (0) x 20;
359
360# Get them from a hash
361sub hWindowPos_set ($$) {
362  my $hash = shift;
363  my $hwnd = (@_ ? shift : $hash->{hwnd} );
364  my $flags;
365  if (exists $hash->{flags}) {
366    $flags = $hash->{flags};
367  } else {			# Set flags according to existing keys in $hash
368    $flags = 0;
369    for my $bit (0..2) {
370      exists $hash->{$_} and $flags |= (1<<$bit) for @{$SWP_keys[$bit]};
371    }
372  }
373  for my $bit (0..2) {		# Check for required keys
374    next unless $flags & (1<<$bit);
375    exists $hash->{$_}
376      or die sprintf "key $_ required for flags=%#x", $flags
377	for @{$SWP_keys[$bit]};
378  }
379  my %h = (%SWP_def, flags => $flags, %$hash);		# Avoid warnings
380  my ($x, $y, $fl, $w, $h, $behind) = @h{ qw(x y flags width height behind) };
381  WindowPos_set($hwnd, $x, $y, $fl, $w, $h, $behind);
382}
383
384sub ChildWindows (;$) {
385  my $hm = OS2::localMorphPM->new(0);
386  my @kids;
387  my $h = BeginEnumWindows(@_ ? shift : 1);	# HWND_DESKTOP
388  my $w;
389  push @kids, $w while $w = GetNextWindow $h;
390  EndEnumWindows $h;
391  @kids;
392}
393
394sub TopLevel ($) {
395  my $d = DesktopWindow;
396  my $w = shift;
397  while (1) {
398    my $p = QueryWindow $w, 5;	# QW_PARENT;
399    return $w if not $p or $p == $d;
400    $w = $p;
401  }
402}
403
404sub FocusWindow_set_keep_Zorder ($) {
405  my $w = shift;
406  my $t = TopLevel $w;
407  my $b = hWindowPos($t)->{behind}; # we are behind this
408  EnableWindowUpdate($t, 0);
409  FocusWindow_set($w);
410# sleep 1;    # Make flicker stronger when present
411  hWindowPos_set {behind => $b}, $t;
412  EnableWindowUpdate($t, 1);
413}
414
415sub ClipbrdText (@) {
416  my $morph = OS2::localMorphPM->new(0);
417  OpenClipbrd();
418  my $txt = unpack 'p', pack 'L', ClipbrdData @_;
419  CloseClipbrd();
420  $txt;
421}
422
423sub ClipbrdText_set ($;$) {
424  my $morph = OS2::localMorphPM->new(0);
425  OpenClipbrd();
426  EmptyClipbrd();				# It may contain other types
427  my ($txt, $no_convert_nl) = (shift, shift);
428  ClipbrdData_set($txt, !$no_convert_nl, @_);
429  CloseClipbrd();
430}
431
432sub MessageBox ($;$$$$$) {
433  my $morph = OS2::localMorphPM->new(0);
434  die "MessageBox needs text" unless @_;
435  push @_ , ($0 eq '-e' ? "Perl one-liner's message" : "$0 message") if @_ == 1;
436  &_MessageBox;
437}
438
439my %pointers;
440
441sub get_pointer ($;$$) {
442  my $id = $_[0];
443  return $pointers{$id} if exists $pointers{$id};
444  $pointers{$id} = &SysPointer;
445}
446
447# $button needs to be of the form 'String', ['String'] or ['String', flag].
448# If ['String'], it is assumed the default button; same for 'String' if $only
449# is set.
450sub process_MB2 ($$;$) {
451  die "process_MB2() needs 2 arguments, got '@_'" unless @_ == 2 or @_ == 3;
452  my ($button, $ret, $only) = @_;
453  # default is BS_PUSHBUTTON, add BS_DEFAULT if $only is set
454  $button = [$button, $only ? 0x400 : 0] unless ref $button eq 'ARRAY';
455  push @$button, 0x400 if @$button == 1; # BS_PUSHBUTTON|BS_DEFAULT
456  die "Button needs to be of the form 'String', ['String'] or ['String', flag]"
457    unless @$button == 2;
458  pack "Z71 x L l", $button->[0], $ret, $button->[1]; # name, retval, flag
459}
460
461# If one button, make it the default one even if it is of 'String' => val form.
462# If icon is of the form 'SP#<number>', load this via SysPointer.
463sub process_MB2_INFO ($;$$$) {
464  my $l = 0;
465  my $out;
466  die "process_MB2_INFO() needs 1..4 arguments" unless @_ and @_ < 5;
467  my $buttons = shift;
468  die "Buttons array should consist of pairs" if @$buttons % 2;
469
470  push @_, 0 unless @_;		# Icon id (pointer)
471  # Box flags (MB_MOVABLE and MB_INFORMATION or MB_CUSTOMICON)
472  push @_, ($_[0] ? 0x4080 : 0x4030) unless @_ > 1;
473  push @_, 0 unless @_ > 2;	# Notify window
474
475  my ($icon, $style, $notify) = (shift, shift, shift);
476  $icon = get_pointer $1 if $icon =~ /^SP#(\d+)\z/;
477  $out = pack "L L L L",	# icon, #buttons, style, notify, buttons
478      $icon, @$buttons/2, $style, $notify;
479  $out .= join '',
480    map process_MB2($buttons->[2*$_], $buttons->[2*$_+1], @$buttons == 2),
481      0..@$buttons/2-1;
482  pack('L', length(pack 'L', 0) + length $out) . $out;
483}
484
485# MessageBox2 'Try this', OS2::Process::process_MB2_INFO([['Dismiss', 0] => 0x1000], OS2::Process::get_pointer(22),0x4080,0), 'me', 1, 0, 0
486# or the shortcut
487# MessageBox2 'Try this', [[['Dismiss', 0] => 0x1000], 'SP#22'], 'me'
488# 0x80 means MB_CUSTOMICON (does not focus?!).  This focuses:
489# MessageBox2 'Try this', [[['Dismiss',0x400] => 0x1000], 0, 0x4030,0]
490# 0x400 means BS_DEFAULT.  This is the same as the shortcut
491# MessageBox2 'Try this', [[Dismiss => 0x1000]]
492sub MessageBox2 ($;$$$$$) {
493  my $morph = OS2::localMorphPM->new(0);
494  die "MessageBox needs text" unless @_;
495  push @_ , [[Dismiss => 0x1000], # Name, retval (BS_PUSHBUTTON|BS_DEFAULT)
496	     #0,		# get_pointer(11),	# SPTR_ICONINFORMATION
497	     #0x4030,		# MB_MOVEABLE | MB_INFORMATION
498	     #0,		# Notify window; was 1==HWND_DESKTOP
499	    ] if @_ == 1;
500  push @_ , ($0 eq '-e' ? "Perl one-liner's message" : "$0's message") if @_ == 2;
501  $_[1] = &process_MB2_INFO(@{$_[1]}) if ref($_[1]) eq 'ARRAY';
502  &_MessageBox2;
503}
504
505# backward compatibility
506*set_title = \&Title_set;
507*get_title = \&Title;
508
509# adapter; display; cbMemory; Configuration; VDHVersion; Flags; HWBufferSize;
510# FullSaveSize; PartSaveSize; EMAdaptersOFF; EMDisplaysOFF;
511sub vioConfig (;$$) {
512  my $data = &_vioConfig;
513  my @out = unpack 'x[S]SSLSSSLLLSS', $data;
514  # If present, offset points to S/S (with only the first work making sense)
515  my (@adaptersEMU, @displayEMU);
516  @displaysEMU = unpack("x[$out[10]]S/S", $data), pop @out if @out > 10;
517  @adaptersEMU = unpack("x[$out[ 9]]S/S", $data), pop @out if @out > 9;
518  $out[9] = $adaptersEMU[0] if @adaptersEMU;
519  $out[10] = $displaysEMU[0] if @displaysEMU;
520  @out;
521}
522
523my @vioConfig = qw(adapter display cbMemory Configuration VDHVersion Flags
524		   HWBufferSize FullSaveSize PartSaveSize EMAdapters EMDisplays);
525
526sub viohConfig (;$$) {
527  my %h;
528  @h{@vioConfig} = &vioConfig;
529  %h;
530}
531
532# fbType; color; col; row; hres; vres; fmt_ID; attrib; buf_addr; buf_length;
533# full_length; partial_length; ext_data_addr;
534sub vioMode() {unpack 'x[S]CCSSSSCCLLLLL', _vioMode}
535
536my @vioMode = qw( fbType color col row hres vres fmt_ID attrib buf_addr
537		  buf_length full_length partial_length ext_data_addr);
538
539sub viohMode() {
540  my %h;
541  @h{@vioMode} = vioMode;
542  %h;
543}
544
545sub viohMode_set {
546  my %h = (viohMode, @_);
547  my $o = pack 'x[S]CCSSSSCCLLLLL', @h{@vioMode};
548  $o = pack 'SCCSSSSCCLLLLL', length $o, @h{@vioMode};
549  _vioMode_set($o);
550}
551
552sub kbdChar (;$$) {unpack 'CCCCSL', &_kbdChar}
553
554my @kbdChar = qw(ascii scancode status nlsstate shifts time);
555sub kbdhChar (;$$) {
556  my %h;
557  @h{@kbdChar} = &kbdChar;
558  %h
559}
560
561sub kbdStatus (;$) {unpack 'x[S]SSSS', &_kbdStatus}
562my @kbdStatus = qw(state turnChar intCharFlags shifts);
563sub kbdhStatus (;$) {
564  my %h;
565  @h{@kbdStatus} = &kbdStatus;
566  %h
567}
568sub kbdhStatus_set {
569  my $h = (@_ % 2 ? shift @_ : 0);
570  my %h = (kbdhStatus($h), @_);
571  my $o = pack 'x[S]SSSS', @h{@kbdStatus};
572  $o = pack 'SSSSS', length $o, @h{@kbdStatus};
573  _kbdStatus_set($o,$h);
574}
575
576
577# Autoload methods go after __END__, and are processed by the autosplit program.
578
5791;
580__END__
581
582=head1 NAME
583
584OS2::Process - exports constants for system() call, and process control on OS2.
585
586=head1 SYNOPSIS
587
588    use OS2::Process;
589    $pid = system(P_PM | P_BACKGROUND, "epm.exe");
590
591=head1 DESCRIPTION
592
593=head2 Optional argument to system()
594
595the builtin function system() under OS/2 allows an optional first
596argument which denotes the mode of the process. Note that this argument is
597recognized only if it is strictly numerical.
598
599You can use either one of the process modes:
600
601	P_WAIT (0)	= wait until child terminates (default)
602	P_NOWAIT	= do not wait until child terminates
603	P_SESSION	= new session
604	P_DETACH	= detached
605	P_PM		= PM program
606
607and optionally add PM and session option bits:
608
609	P_DEFAULT (0)	= default
610	P_MINIMIZE	= minimized
611	P_MAXIMIZE	= maximized
612	P_FULLSCREEN	= fullscreen (session only)
613	P_WINDOWED	= windowed (session only)
614
615	P_FOREGROUND	= foreground (if running in foreground)
616	P_BACKGROUND	= background
617
618	P_NOCLOSE	= don't close window on exit (session only)
619
620	P_QUOTE		= quote all arguments
621	P_TILDE		= MKS argument passing convention
622	P_UNRELATED	= do not kill child when father terminates
623
624=head2 Access to process properties
625
626On OS/2 processes have the usual I<parent/child> semantic;
627additionally, there is a hierarchy of sessions with their own
628I<parent/child> tree.  A session is either a FS session, or a windowed
629pseudo-session created by PM.  A session is a "unit of user
630interaction", a change to in/out settings in one of them does not
631affect other sessions.
632
633=over
634
635=item my_type()
636
637returns the type of the current process (one of
638"FS", "DOS", "VIO", "PM", "DETACH" and "UNKNOWN"), or C<undef> on error.
639
640=item C<file_type(file)>
641
642returns the type of the executable file C<file>, or
643dies on error.  The bits 0-2 of the result contain one of the values
644
645=over
646
647=item C<T_NOTSPEC> (0)
648
649Application type is not specified in the executable header.
650
651=item C<T_NOTWINDOWCOMPAT> (1)
652
653Application type is not-window-compatible.
654
655=item C<T_WINDOWCOMPAT> (2)
656
657Application type is window-compatible.
658
659=item C<T_WINDOWAPI> (3)
660
661Application type is window-API.
662
663=back
664
665The remaining bits should be masked with the following values to
666determine the type of the executable:
667
668=over
669
670=item C<T_BOUND> (8)
671
672Set to 1 if the executable file has been "bound" (by the BIND command)
673as a Family API application. Bits 0, 1, and 2 still apply.
674
675=item C<T_DLL> (0x10)
676
677Set to 1 if the executable file is a dynamic link library (DLL)
678module. Bits 0, 1, 2, 3, and 5 will be set to 0.
679
680=item C<T_DOS> (0x20)
681
682Set to 1 if the executable file is in PC/DOS format. Bits 0, 1, 2, 3,
683and 4 will be set to 0.
684
685=item C<T_PHYSDRV> (0x40)
686
687Set to 1 if the executable file is a physical device driver.
688
689=item C<T_VIRTDRV> (0x80)
690
691Set to 1 if the executable file is a virtual device driver.
692
693=item C<T_PROTDLL> (0x100)
694
695Set to 1 if the executable file is a protected-memory dynamic link
696library module.
697
698=item C<T_32BIT> (0x4000)
699
700Set to 1 for 32-bit executable files.
701
702=back
703
704file_type() may croak with one of the strings C<"Invalid EXE
705signature"> or C<"EXE marked invalid"> to indicate typical error
706conditions.  If given non-absolute path, will look on C<PATH>, will
707add extension F<.exe> if no extension is present (add extension F<.>
708to suppress).
709
710=item C<@list = process_codepages()>
711
712the first element is the currently active codepage, up to 2 additional
713entries specify the system's "prepared codepages": the codepages the
714user can switch to.  The active codepage of a process is one of the
715prepared codepages of the system (if present).
716
717=item C<process_codepage_set($cp)>
718
719sets the currently active codepage.  [Affects printer output, in/out
720codepages of sessions started by this process, and the default
721codepage for drawing in PM; is inherited by kids.  Does not affect the
722out- and in-codepages of the session.]
723
724=item ppid()
725
726returns the PID of the parent process.
727
728=item C<ppidOf($pid = $$)>
729
730returns the PID of the parent process of $pid.  -1 on error.
731
732=item C<sidOf($pid = $$)>
733
734returns the session id of the process id $pid.  -1 on error.
735
736=back
737
738=head2 Control of VIO sessions
739
740VIO applications are applications running in a text-mode session.
741
742=over
743
744=item out_codepage()
745
746gets code page used for screen output (glyphs).  -1 means that a user font
747was loaded.
748
749=item C<out_codepage_set($cp)>
750
751sets code page used for screen output (glyphs).  -1 switches to a preloaded
752user font.  -2 switches off the preloaded user font.
753
754=item in_codepage()
755
756gets code page used for keyboard input.  0 means that a hardware codepage
757is used.
758
759=item C<in_codepage_set($cp)>
760
761sets code page used for keyboard input.
762
763=item C<($w, $h) = scrsize()>
764
765width and height of the given console window in character cells.
766
767=item C<scrsize_set([$w, ] $h)>
768
769set height (and optionally width) of the given console window in
770character cells.  Use 0 size to keep the old size.
771
772=item C<($s, $e, $w, $a) = cursor()>
773
774gets start/end lines of the blinking cursor in the charcell, its width
775(1 on text modes) and attribute (-1 for hidden, in text modes other
776values mean visible, in graphic modes color).
777
778=item C<cursor_set($s, $e, [$w [, $a]])>
779
780sets start/end lines of the blinking cursor in the charcell.  Negative
781values mean percents of the character cell height.
782
783=item screen()
784
785gets a buffer with characters and attributes of the screen.
786
787=item C<screen_set($buffer)>
788
789restores the screen given the result of screen().  E.g., if the file
790C<$file> contains the screen contents, then
791
792  open IN, $file or die;
793  binmode IN;
794  read IN, $in, -s IN;
795  $s = screen;
796  $in .= qq(\0) x (length($s) - length $in);
797  substr($in, length $s) = '';
798  screen_set $in;
799
800will restore the screen content even if the height of the window
801changed (if the width changed, more manipulation is needed).
802
803=back
804
805=head2 Control of the process list
806
807With the exception of Title_set(), all these calls require that PM is
808running, they would not work under alternative Session Managers.
809
810=over
811
812=item process_entry()
813
814returns a list of the following data:
815
816=over
817
818=item
819
820Title of the process (in the C<Ctrl-Esc> list);
821
822=item
823
824window handle of switch entry of the process (in the C<Ctrl-Esc> list);
825
826=item
827
828window handle of the icon of the process;
829
830=item
831
832process handle of the owner of the entry in C<Ctrl-Esc> list;
833
834=item
835
836process id of the owner of the entry in C<Ctrl-Esc> list;
837
838=item
839
840session id of the owner of the entry in C<Ctrl-Esc> list;
841
842=item
843
844whether visible in C<Ctrl-Esc> list;
845
846=item
847
848whether item cannot be switched to (note that it is not actually
849grayed in the C<Ctrl-Esc> list));
850
851=item
852
853whether participates in jump sequence;
854
855=item
856
857program type.  Possible values are:
858
859     PROG_DEFAULT                       0
860     PROG_FULLSCREEN                    1
861     PROG_WINDOWABLEVIO                 2
862     PROG_PM                            3
863     PROG_VDM                           4
864     PROG_WINDOWEDVDM                   7
865
866Although there are several other program types for WIN-OS/2 programs,
867these do not show up in this field. Instead, the PROG_VDM or
868PROG_WINDOWEDVDM program types are used. For instance, for
869PROG_31_STDSEAMLESSVDM, PROG_WINDOWEDVDM is used. This is because all
870the WIN-OS/2 programs run in DOS sessions. For example, if a program
871is a windowed WIN-OS/2 program, it runs in a PROG_WINDOWEDVDM
872session. Likewise, if it's a full-screen WIN-OS/2 program, it runs in
873a PROG_VDM session.
874
875=item
876
877switch-entry handle.
878
879=back
880
881Optional arguments: the pid and the window-handle of the application running
882in the OS/2 session to query.
883
884=item process_hentry()
885
886similar to process_entry(), but returns a hash reference, the keys being
887
888  title owner_hwnd icon_hwnd owner_phandle owner_pid owner_sid
889  visible nonswitchable jumpable ptype sw_entry
890
891(a copy of the list of keys is in @hentry_fields).
892
893=item process_entries()
894
895similar to process_entry(), but returns a list of array reference for all
896the elements in the switch list (one controlling C<Ctrl-Esc> window).
897
898=item process_hentries()
899
900similar to process_hentry(), but returns a list of hash reference for all
901the elements in the switch list (one controlling C<Ctrl-Esc> window).
902
903=item change_entry()
904
905changes a process entry, arguments are the same as process_entry() returns.
906
907=item change_entryh()
908
909Similar to change_entry(), but takes a hash reference as an argument.
910
911=item process_hwnd()
912
913returns the C<owner_hwnd> of the process entry (for VIO windowed processes
914this is the frame window of the session).
915
916=item Title()
917
918returns the text of the task switch menu entry of the current session.
919(There is no way to get this info in non-standard Session Managers.  This
920implementation is a shortcut via process_entry().)
921
922=item C<Title_set(newtitle)>
923
924tries two different interfaces.  The Session Manager one does not work
925with some windows (if the title is set from the start).
926This is a limitation of OS/2, in such a case $^E is set to 372 (type
927
928  help 372
929
930for a funny - and wrong  - explanation ;-).  In such cases a
931direct-manipulation of low-level entries is used (same as bothTitle_set()).
932Keep in mind that some versions of OS/2 leak memory with such a manipulation.
933
934=item winTitle()
935
936returns text of the titlebar of the current process' window.
937
938=item C<winTitle_set(newtitle)>
939
940sets text of the titlebar of the current process' window.  The change does not
941affect the text of the switch entry of the current window.
942
943=item C<swTitle_set(newtitle)>
944
945sets text of the task switch menu entry of the current process' window.  [There
946is no API to query this title.]  Does it via SwitchEntry interface,
947not Session manager interface.  The change does not affect the text of the
948titlebar of the current window.
949
950=item C<bothTitle_set(newtitle)>
951
952sets text of the titlebar and task switch menu of the current process' window
953via direct manipulation of the windows' texts.
954
955=item C<SwitchToProgram([$sw_entry])>
956
957switch to session given by a switch list handle (defaults to the entry of our process).
958
959Use of this function causes another window (and its related windows)
960of a PM session to appear on the front of the screen, or a switch to
961another session in the case of a non-PM program. In either case,
962the keyboard (and mouse for the non-PM case) input is directed to
963the new program.
964
965=back
966
967=head2 Control of the PM windows
968
969Some of these API's require sending a message to the specified window.
970In such a case the process needs to be a PM process, or to be morphed
971to a PM process via OS2::MorphPM().
972
973For a temporary morphing to PM use L<OS2::localMorphPM class>.
974
975Keep in mind that PM windows are engaged in 2 "orthogonal" window
976trees, as well as in the z-order list.
977
978One tree is given by the I<parent/child> relationship.  This
979relationship affects drawing (child is drawn relative to its parent
980(lower-left corner), and the drawing is clipped by the parent's
981boundary; parent may request that I<it's> drawing is clipped to be
982confined to the outsize of the childs and/or siblings' windows);
983hiding; minimizing/restoring; and destroying windows.
984
985Another tree (not necessarily connected?) is given by I<ownership>
986relationship.  Ownership relationship assumes cooperation of the
987engaged windows via passing messages on "important events"; e.g.,
988scrollbars send information messages when the "bar" is moved, menus
989send messages when an item is selected; frames
990move/hide/unhide/minimize/restore/change-z-order-of owned frames when
991the owner is moved/etc., and destroy the owned frames (even when these
992frames are not descendants) when the owner is destroyed; etc.  [An
993important restriction on ownership is that owner should be created by
994the same thread as the owned thread, so they engage in the same
995message queue.]
996
997Windows may be in many different state: Focused (take keyboard events) or not,
998Activated (=Frame windows in the I<parent/child> tree between the root and
999the window with the focus; usually indicate such "active state" by titlebar
1000highlights, and take mouse events) or not, Enabled/Disabled (this influences
1001the ability to update the graphic, and may change appearance, as for
1002enabled/disabled buttons), Visible/Hidden, Minimized/Maximized/Restored, Modal
1003or not, etc.
1004
1005The APIs below all die() on error with the message being $^E.
1006
1007=over
1008
1009=item C<WindowText($hwnd)>
1010
1011gets "a text content" of a window.  Requires (morphing to) PM.
1012
1013=item C<WindowText_set($hwnd, $text)>
1014
1015sets "a text content" of a window.  Requires (morphing to) PM.
1016
1017=item C<($x, $y, $flags, $width, $height, $behind, @rest) = WindowPos($hwnd)>
1018
1019gets window position info as 8 integers (of C<SWP>), in the order suitable
1020for WindowPos_set().  @rest is marked as "reserved" in PM docs.  $flags
1021is a combination of C<SWP_*> constants.
1022
1023=item C<$hash = hWindowPos($hwnd)>
1024
1025gets window position info as a hash reference; the keys are C<flags width
1026height x y behind hwnd reserved1 reserved2>.
1027
1028Example:
1029
1030  exit unless $hash->{flags} & SWP_MAXIMIZE;	# Maximized
1031
1032=item C<WindowPos_set($hwnd, $x, $y, $flags = SWP_MOVE, $width = 0, $height = 0, $behind = HWND_TOP)>
1033
1034Set state of the window: position, size, zorder, show/hide, activation,
1035minimize/maximize/restore etc.  Which of these operations to perform
1036is governed by $flags.
1037
1038=item C<hWindowPos_set($hash, [$hwnd])>
1039
1040Same as C<WindowPos_set>, but takes the position from keys C<fl width height
1041x y behind hwnd> of the hash referenced by $hash.  If $hwnd is explicitly
1042specified, it overrides C<$hash->{hwnd}>.  If $hash->{flags} is not specified,
1043it is calculated basing on the existing keys of $hash.  Requires (morphing to) PM.
1044
1045Example:
1046
1047  hWindowPos_set {flags => SWP_MAXIMIZE}, $hwnd; # Maximize
1048
1049=item C<($pid, $tid) = WindowProcess($hwnd)>
1050
1051gets I<PID> and I<TID> of the process associated to the window.
1052
1053=item C<ClassName($hwnd)>
1054
1055returns the class name of the window.
1056
1057If this window is of any of the preregistered WC_* classes the class
1058name returned is in the form "#nnnnn", where "nnnnn" is a group
1059of up to five digits that corresponds to the value of the WC_* class name
1060constant.
1061
1062=item FocusWindow()
1063
1064returns the handle of the focus window.  Optional argument for specifying
1065the desktop to use.
1066
1067=item C<FocusWindow_set($hwnd)>
1068
1069set the focus window by handle.  Optional argument for specifying the desktop
1070to use.  E.g, the first entry in program_entries() is the C<Ctrl-Esc> list.
1071To show an application, use either one of
1072
1073       WinShowWindow( $hwnd, 1 );
1074       FocusWindow_set( $hwnd );
1075       SwitchToProgram($switch_handle);
1076
1077(Which work with alternative focus-to-front policies?)  Requires
1078(morphing to) PM.
1079
1080Switching focus to currently-unfocused window moves the window to the
1081front in Z-order; use FocusWindow_set_keep_Zorder() to avoid this.
1082
1083=item C<FocusWindow_set_keep_Zorder($hwnd)>
1084
1085same as FocusWindow_set(), but preserves the Z-order of windows.
1086
1087=item C<ActiveWindow([$parentHwnd])>
1088
1089gets the active subwindow's handle for $parentHwnd or desktop.
1090Returns FALSE if none.
1091
1092=item C<ActiveWindow_set($hwnd, [$parentHwnd])>
1093
1094sets the active subwindow's handle for $parentHwnd or desktop.  Requires (morphing to) PM.
1095
1096=item C<ShowWindow($hwnd [, $show])>
1097
1098Set visible/hidden flag of the window.  Default: $show is TRUE.
1099
1100=item C<EnableWindowUpdate($hwnd [, $update])>
1101
1102Set window visibility state flag for the window for subsequent drawing.
1103No actual drawing is done at this moment.  Use C<ShowWindow($hwnd, $state)>
1104when redrawing is needed.  While update is disabled, changes to the "window
1105state" do not change the appearance of the window.  Default: $update is TRUE.
1106
1107(What is manipulated is the bit C<WS_VISIBLE> of the window style.)
1108
1109=item C<EnableWindow($hwnd [, $enable])>
1110
1111Set the window enabled state.  Default: $enable is TRUE.
1112
1113Results in C<WM_ENABLED> message sent to the window.  Typically, this
1114would change the appearence of the window.  If at the moment of disabling
1115focus is in the window (or a descendant), focus is lost (no focus anywhere).
1116If focus is needed, it can be reassigned explicitly later.
1117
1118=item IsWindowEnabled(), IsWindowVisible(), IsWindowShowing()
1119
1120these functions take $hwnd as an argument.  IsWindowEnabled() queries
1121the state changed by EnableWindow(), IsWindowVisible() the state changed
1122by ShowWindow(), IsWindowShowing() is true if there is a part of the window
1123visible on the screen.
1124
1125=item C<PostMsg($hwnd, $msg, $mp1, $mp2)>
1126
1127post message to a window.  The meaning of $mp1, $mp2 is specific for each
1128message id $msg, they default to 0.  E.g.,
1129
1130  use OS2::Process qw(:DEFAULT WM_SYSCOMMAND WM_CONTEXTMENU
1131		      WM_SAVEAPPLICATION WM_QUIT WM_CLOSE
1132		      SC_MAXIMIZE SC_RESTORE);
1133  $hwnd = process_hentry()->{owner_hwnd};
1134  # Emulate choosing `Restore' from the window menu:
1135  PostMsg $hwnd, WM_SYSCOMMAND, MPFROMSHORT(SC_RESTORE); # Not immediate
1136
1137  # Emulate `Show-Contextmenu' (Double-Click-2), two ways:
1138  PostMsg ActiveWindow, WM_CONTEXTMENU;
1139  PostMsg FocusWindow, WM_CONTEXTMENU;
1140
1141  /* Emulate `Close' */
1142  PostMsg ActiveWindow, WM_CLOSE;
1143
1144  /* Same but with some "warnings" to the application */
1145  $hwnd = ActiveWindow;
1146  PostMsg $hwnd, WM_SAVEAPPLICATION;
1147  PostMsg $hwnd, WM_CLOSE;
1148  PostMsg $hwnd, WM_QUIT;
1149
1150In fact, MPFROMSHORT() may be omitted above.
1151
1152For messages to other processes, messages which take/return a pointer are
1153not supported.
1154
1155=item C<MP*()>
1156
1157The functions MPFROMSHORT(), MPVOID(), MPFROMCHAR(), MPFROM2SHORT(),
1158MPFROMSH2CH(), MPFROMLONG() can be used the same way as from C.  Use them
1159to construct parameters $m1, $m2 to PostMsg().
1160
1161These functions are not exported by default.
1162
1163=item C<$eh = BeginEnumWindows($hwnd)>
1164
1165starts enumerating immediate child windows of $hwnd in z-order.  The
1166enumeration reflects the state at the moment of BeginEnumWindows() calls;
1167use IsWindow() to be sure.  All the functions in this group require (morphing to) PM.
1168
1169=item C<$kid_hwnd = GetNextWindow($eh)>
1170
1171gets the next kid in the list.  Gets 0 on error or when the list ends.
1172
1173=item C<EndEnumWindows($eh)>
1174
1175End enumeration and release the list.
1176
1177=item C<@list = ChildWindows([$hwnd])>
1178
1179returns the list of child windows at the moment of the call.  Same remark
1180as for enumeration interface applies.  Defaults to HWND_DESKTOP.
1181Example of usage:
1182
1183  sub l {
1184    my ($o,$h) = @_;
1185    printf ' ' x $o . "%#x\n", $h;
1186    l($o+2,$_) for ChildWindows $h;
1187  }
1188  l 0, $HWND_DESKTOP
1189
1190=item C<IsWindow($hwnd)>
1191
1192true if the window handle is still valid.
1193
1194=item C<QueryWindow($hwnd, $type)>
1195
1196gets the handle of a related window.  $type should be one of C<QW_*> constants.
1197
1198=item C<IsChild($hwnd, $parent)>
1199
1200return TRUE if $hwnd is a descendant of $parent.
1201
1202=item C<WindowFromId($hwnd, $id)>
1203
1204return a window handle of a child of $hwnd with the given $id.
1205
1206  hwndSysMenu = WinWindowFromID(hwndDlg, FID_SYSMENU);
1207  WinSendMsg(hwndSysMenu, MM_SETITEMATTR,
1208      MPFROM2SHORT(SC_CLOSE, TRUE),
1209      MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
1210
1211=item C<WindowFromPoint($x, $y [, $hwndParent [, $descedantsToo]])>
1212
1213gets a handle of a child of $hwndParent at C<($x,$y)>.  If $descedantsToo
1214(defaulting to 1) then children of children may be returned too.  May return
1215$hwndParent (defaults to desktop) if no suitable children are found,
1216or 0 if the point is outside the parent.
1217
1218$x and $y are relative to $hwndParent.
1219
1220=item C<EnumDlgItem($dlgHwnd, $type [, $relativeHwnd])>
1221
1222gets a dialog item window handle for an item of type $type of $dlgHwnd
1223relative to $relativeHwnd, which is descendant of $dlgHwnd.
1224$relativeHwnd may be specified if $type is EDI_FIRSTTABITEM or
1225EDI_LASTTABITEM.
1226
1227The return is always an immediate child of hwndDlg, even if hwnd is
1228not an immediate child window.  $type may be
1229
1230=over
1231
1232=item EDI_FIRSTGROUPITEM
1233
1234First item in the same group.
1235
1236=item EDI_FIRSTTABITEM
1237
1238First item in dialog with style WS_TABSTOP. hwnd is ignored.
1239
1240=item EDI_LASTGROUPITEM
1241
1242Last item in the same group.
1243
1244=item EDI_LASTTABITEM
1245
1246Last item in dialog with style WS_TABSTOP. hwnd is ignored.
1247
1248=item EDI_NEXTGROUPITEM
1249
1250Next item in the same group. Wraps around to beginning of group when
1251the end of the group is reached.
1252
1253=item EDI_NEXTTABITEM
1254
1255Next item with style WS_TABSTOP. Wraps around to beginning of dialog
1256item list when end is reached.
1257
1258=item EDI_PREVGROUPITEM
1259
1260Previous item in the same group. Wraps around to end of group when the
1261start of the group is reached. For information on the WS_GROUP style,
1262see Window Styles.
1263
1264=item EDI_PREVTABITEM
1265
1266Previous item with style WS_TABSTOP. Wraps around to end of dialog
1267item list when beginning is reached.
1268
1269=back
1270
1271=item DesktopWindow()
1272
1273gets the actual window handle of the PM desktop; most APIs accept the
1274pseudo-handle C<HWND_DESKTOP> instead.  Keep in mind that the WPS
1275desktop (one with WindowText() being C<"Desktop">) is a different beast?!
1276
1277=item TopLevel($hwnd)
1278
1279gets the toplevel window of $hwnd.
1280
1281=item ResetWinError()
1282
1283Resets $^E.  One may need to call it before the C<Win*>-class APIs which may
1284return 0 during normal operation.  In such a case one should check both
1285for return value being zero and $^E being non-zero.  The following APIs
1286do ResetWinError() themselves, thus do not need an explicit one:
1287
1288  WindowPtr
1289  WindowULong
1290  WindowUShort
1291  WindowTextLength
1292  ActiveWindow
1293  PostMsg
1294
1295This function is normally not needed.  Not exported by default.
1296
1297=back
1298
1299=head2 Control of the PM data
1300
1301=over
1302
1303=item ActiveDesktopPathname()
1304
1305gets the path of the directory which corresponds to Desktop.
1306
1307=item ClipbrdText()
1308
1309gets the content of the clipboard.  An optional argument is the format
1310of the data in the clipboard (defaults to C<CF_TEXT>).
1311
1312Note that the usual convention is to have clipboard data with
1313C<"\r\n"> as line separators.
1314
1315=item ClipbrdText_set($txt)
1316
1317sets the text content of the clipboard.  Unless the optional argument
1318is TRUE, will convert newlines to C<"\r\n">.  Another optional
1319argument is the format of the data in the clipboard (defaults to
1320C<CF_TEXT>).
1321
1322=item 	InvalidateRect
1323
1324=item	CreateFrameControl
1325
1326=item	ClipbrdFmtInfo
1327
1328=item	ClipbrdOwner
1329
1330=item	ClipbrdViewer
1331
1332=item	ClipbrdData
1333
1334=item	OpenClipbrd
1335
1336=item	CloseClipbrd
1337
1338=item	ClipbrdData_set
1339
1340=item	ClipbrdOwner_set
1341
1342=item	ClipbrdViewer_set
1343
1344=item	EnumClipbrdFmts
1345
1346=item	EmptyClipbrd
1347
1348=item	AddAtom
1349
1350=item	FindAtom
1351
1352=item	DeleteAtom
1353
1354=item	AtomUsage
1355
1356=item	AtomName
1357
1358=item	AtomLength
1359
1360=item	SystemAtomTable
1361
1362=item	CreateAtomTable
1363
1364=item	DestroyAtomTable
1365
1366Low-level methods to access clipboard and the atom table(s).
1367
1368=back
1369
1370=head1 OS2::localMorphPM class
1371
1372This class morphs the process to PM for the duration of the given scope.
1373
1374  {
1375    my $h = OS2::localMorphPM->new(0);
1376    # Do something
1377  }
1378
1379The argument has the same meaning as one to OS2::MorphPM().  Calls can
1380nest with internal ones being NOPs.
1381
1382=head1 TODO
1383
1384Add tests for:
1385
1386	SwitchToProgram
1387	ClassName
1388	out_codepage
1389	out_codepage_set
1390	in_codepage
1391	in_codepage_set
1392	cursor
1393	cursor_set
1394	screen
1395	screen_set
1396	process_codepages
1397	QueryWindow
1398	EnumDlgItem
1399        WindowPtr
1400        WindowULong
1401        WindowUShort
1402        SetWindowBits
1403        SetWindowPtr
1404        SetWindowULong
1405        SetWindowUShort
1406	my_type
1407	file_type
1408	scrsize
1409	scrsize_set
1410
1411Document and test: Query/SetWindowULong/Short/Ptr, SetWindowBits.
1412InvalidateRect, CreateFrameControl, ClipbrdFmtInfo ClipbrdOwner
1413ClipbrdViewer ClipbrdData OpenClipbrd CloseClipbrd ClipbrdData_set
1414ClipbrdOwner_set ClipbrdViewer_set EnumClipbrdFmts EmptyClipbrd
1415AddAtom FindAtom DeleteAtom AtomUsage AtomName AtomLength
1416SystemAtomTable CreateAtomTable DestroyAtomTable
1417
1418Implement SOMETHINGFROMMR.
1419
1420
1421  >But I wish to change the default button if the user enters some
1422  >text into an entryfield.  I can detect the entry ok, but can't
1423  >seem to get the button to change to default.
1424  >
1425  >No matter what message I send it, it's being ignored.
1426
1427  You need to get the style of the buttons using WinQueryWindowULong/QWL_STYLE,
1428  set and reset the BS_DEFAULT bits as appropriate and then use
1429  WinSetWindowULong/QWL_STYLE to set the button style.
1430  Something like this:
1431    hwnd1 = WinWindowFromID (hwnd, id1);
1432    hwnd2 = WinWindowFromID (hwnd, id2);
1433    style1 = WinQueryWindowULong (hwnd1, QWL_STYLE);
1434    style2 = WinQueryWindowULong (hwnd2, QWL_STYLE);
1435    style1 |= style2 & BS_DEFAULT;
1436    style2 &= ~BS_DEFAULT;
1437    WinSetWindowULong (hwnd1, QWL_STYLE, style1);
1438    WinSetWindowULong (hwnd2, QWL_STYLE, style2);
1439
1440 > How to do query and change a frame creation flags for existing window?
1441
1442 Set the style bits that correspond to the FCF_* flag for the frame
1443 window and then send a WM_UPDATEFRAME message with the appropriate FCF_*
1444 flag in mp1.
1445
1446 ULONG ulFrameStyle;
1447 ulFrameStyle = WinQueryWindowULong( WinQueryWindow(hwnd, QW_PARENT),
1448 QWL_STYLE );
1449 ulFrameStyle = (ulFrameStyle & ~FS_SIZEBORDER) | FS_BORDER;
1450 WinSetWindowULong(   WinQueryWindow(hwnd, QW_PARENT),
1451                      QWL_STYLE,
1452                      ulFrameStyle );
1453 WinSendMsg( WinQueryWindow(hwnd, QW_PARENT),
1454             WM_UPDATEFRAME,
1455             MPFROMP(FCF_SIZEBORDER),
1456             MPVOID );
1457
1458 If the FCF_* flags you want to change does not have a corresponding FS_*
1459 style (i.e. the FCF_* flag corresponds to the presence/lack of a frame
1460 control rather than a property of the frame itself) then you create or
1461 destroy the appropriate control window using the correct FID_* window
1462 identifier and then send the WM_UPDATEFRAME message with the appropriate
1463 FCF_* flag in mp1.
1464
1465 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
1466  |  SetFrameBorder()                                                          |
1467  |    Changes a frame window's border to the requested type.                  |
1468  |                                                                            |
1469  |  Parameters on entry:                                                      |
1470  |    hwndFrame     -> Frame window whose border is to be changed.            |
1471  |    ulBorderStyle -> Type of border to change to.                           |
1472  |                                                                            |
1473  |  Returns:                                                                  |
1474  |    BOOL          -> Success indicator.                                     |
1475  |                                                                            |
1476  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1477 BOOL SetFrameBorder( HWND hwndFrame, ULONG ulBorderType )  {
1478   ULONG  ulFrameStyle;
1479   BOOL   fSuccess = TRUE;
1480
1481   ulFrameStyle = WinQueryWindowULong( hwndFrame, QWL_STYLE );
1482
1483   switch ( ulBorderType )  {
1484     case FS_SIZEBORDER :
1485       ulFrameStyle = (ulFrameStyle & ~(FS_DLGBORDER | FS_BORDER))
1486                      | FS_SIZEBORDER;
1487       break;
1488
1489     case FS_DLGBORDER :
1490       ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_BORDER))
1491                      | FS_DLGBORDER;
1492       break;
1493
1494     case FS_BORDER :
1495       ulFrameStyle = (ulFrameStyle & ~(FS_SIZEBORDER | FS_DLGBORDER))
1496                      | FS_BORDER;
1497       break;
1498
1499     default :
1500       fSuccess = FALSE;
1501       break;
1502   }  // end switch
1503
1504   if ( fSuccess )  {
1505     fSuccess = WinSetWindowULong( hwndFrame, QWL_STYLE, ulFrameStyle );
1506
1507     if ( fSuccess )  {
1508       fSuccess = (BOOL)WinSendMsg( hwndFrame, WM_UPDATEFRAME, 0, 0 );
1509       if ( fSuccess )
1510         fSuccess = WinInvalidateRect( hwndFrame, NULL, TRUE );
1511     }
1512   }
1513
1514   return ( fSuccess );
1515
1516 }  // End SetFrameBorder()
1517
1518         hwndMenu=WinLoadMenu(hwndParent,NULL,WND_IMAGE);
1519         WinSetWindowUShort(hwndMenu,QWS_ID,FID_MENU);
1520         ulStyle=WinQueryWindowULong(hwndMenu,QWL_STYLE);
1521         WinSetWindowULong(hwndMenu,QWL_STYLE,ulStyle|MS_ACTIONBAR);
1522         WinSendMsg(hwndParent,WM_UPDATEFRAME,MPFROMSHORT(FCF_MENU),0L);
1523
1524  OS/2-windows have another "parent" called the *owner*,
1525  which must be set separately - to get a close relationship:
1526
1527    WinSetOwner (hwndFrameChild, hwndFrameMain);
1528
1529  Now your child should move with your main window!
1530  And always stays on top of it....
1531
1532  To avoid this, for example for dialogwindows, you can
1533  also "disconnect" this relationship with:
1534
1535    WinSetWindowBits (hwndFrameChild, QWL_STYLE
1536                      , FS_NOMOVEWITHOWNER
1537                      , FS_NOMOVEWITHOWNER);
1538
1539 Adding a button icon later:
1540
1541 /* switch the button style to BS_MINIICON */
1542 WinSetWindowBits(hwndBtn, QWL_STYLE, BS_MINIICON, BS_MINIICON) ;
1543
1544 /* set up button control data */
1545 BTNCDATA    bcd;
1546 bcd.cb = sizeof(BTNCDATA);
1547 bcd.hImage = WinLoadPointer(HWND_DESKTOP, dllHandle, ID_ICON_BUTTON1) ;
1548 bcd.fsCheckState = bcd.fsHiliteState = 0 ;
1549
1550
1551 WNDPARAMS   wp;
1552 wp.fsStatus = WPM_CTLDATA;
1553 wp.pCtlData = &bcd;
1554
1555 /* add the icon on the button */
1556 WinSendMsg(hwndBtn, WM_SETWINDOWPARAMS, (MPARAM)&wp, NULL);
1557
1558 MO> Can anyone tell what OS/2 expects of an application to be properly
1559 MO> minimized to the desktop?
1560 case WM MINMAXFRAME :
1561 {
1562   BOOL  fShow = ! (((PSWP) mp1)->fl & SWP MINIMIZE);
1563   HENUM henum;
1564
1565   HWND  hwndChild;
1566
1567   WinEnableWindowUpdate ( hwnd, FALSE );
1568
1569   for (henum=WinBeginEnumWindows(hwnd);
1570        (hwndChild = WinGetNextWindow (henum)) != 0; )
1571   WinShowWindow ( hwndChild, fShow );
1572
1573   WinEndEnumWindows ( henum );
1574   WinEnableWindowUpdate ( hwnd, TRUE );
1575 }
1576 break;
1577
1578Why C<hWindowPos DesktopWindow> gives C<< behind => HWND_TOP >>?
1579
1580=head1 $^E
1581
1582the majority of the APIs of this module set $^E on failure (no matter
1583whether they die() on failure or not).  By the semantic of PM API
1584which returns something other than a boolean, it is impossible to
1585distinguish failure from a "normal" 0-return.  In such cases C<$^E ==
15860> indicates an absence of error.
1587
1588=head1 EXPORTS
1589
1590In addition to symbols described above, the following constants (available
1591also via module C<OS2::Process::Const>) are exportable.  Note that these
1592symbols live in package C<OS2::Process::Const>, they are not available
1593by full name through C<OS2::Process>!
1594
1595  HWND_*		Standard (abstract) window handles
1596  WM_*			Message ids
1597  SC_*			WM_SYSCOMMAND flavor
1598  SWP_*			Size/move etc flag
1599  WC_*			Standard window classes
1600  PROG_*		Program category (PM, VIO etc)
1601  QW_*			Query-Window flag
1602  EDI_*			Enumerate-Dialog-Item code
1603  WS_*			Window Style flag
1604  QWS_*			Query-window-UShort offsets
1605  QWP_*			Query-window-pointer offsets
1606  QWL_*			Query-window-ULong offsets
1607  FF_*			Frame-window state flags
1608  FI_*			Frame-window information flags
1609  LS_*			List box styles
1610  FS_*			Frame style
1611  FCF_*			Frame creation flags
1612  BS_*			Button style
1613  MS_*			Menu style
1614  TBM_*			Title bar messages?
1615  CF_*			Clipboard formats
1616  CFI_*			Clipboard storage type
1617  FID_*			ids of subwindows of frames
1618
1619=head1 BUGS
1620
1621whether a given API dies or returns FALSE/empty-list on error may be
1622confusing.  This may change in the future.
1623
1624=head1 AUTHOR
1625
1626Andreas Kaiser <ak@ananke.s.bawue.de>,
1627Ilya Zakharevich <ilya@math.ohio-state.edu>.
1628
1629=head1 SEE ALSO
1630
1631C<spawn*>() system calls, L<OS2::Proc> and L<OS2::WinObject> modules.
1632
1633=cut
1634