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