Typos in *.p[lm]
[p5sagit/p5-mst-13.2.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.01";
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         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 );
187 our @EXPORT_OK = qw(
188         ResetWinError
189         MPFROMSHORT
190         MPVOID
191         MPFROMCHAR
192         MPFROM2SHORT
193         MPFROMSH2CH
194         MPFROMLONG
195 );
196
197 our $AUTOLOAD;
198
199 sub 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
219 sub 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
232 sub 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
244 sub Title () { (process_entry())[0] }
245
246 # *Title_set = \&sesmgr_title_set;
247
248 sub swTitle_set_sw {
249   my ($title, @sw) = @_;
250   $sw[0] = $title;
251   change_entry(@sw);
252 }
253
254 sub swTitle_set ($) {
255   my (@sw) = process_entry();
256   swTitle_set_sw(shift, @sw);
257 }
258
259 sub winTitle_set_sw {
260   my ($title, @sw) = @_;
261   my $h = OS2::localMorphPM->new(0);
262   WindowText_set $sw[1], $title;
263 }
264
265 sub winTitle_set ($) {
266   my (@sw) = process_entry();
267   winTitle_set_sw(shift, @sw);
268 }
269
270 sub winTitle () {
271   my (@sw) = process_entry();
272   my $h = OS2::localMorphPM->new(0);
273   WindowText $sw[1];
274 }
275
276 sub 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
283 sub 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
292 sub process_entry { swentry_expand(process_swentry(@_)) }
293
294 our @hentry_fields = qw( title owner_hwnd icon_hwnd 
295                          owner_phandle owner_pid owner_sid
296                          visible nonswitchable jumpable ptype sw_entry );
297
298 sub swentry_hexpand ($) {
299   my %h;
300   @h{@hentry_fields} = swentry_expand(shift);
301   \%h;
302 }
303
304 sub process_hentry { swentry_hexpand(process_swentry(@_)) }
305 sub process_hwnd { process_hentry()->{owner_hwnd} }
306
307 my $swentry_size = swentry_size();
308
309 sub 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
318 sub process_entries () {
319   map [swentry_expand($_)], sw_entries;
320 }
321
322 sub process_hentries () {
323   map swentry_hexpand($_), sw_entries;
324 }
325
326 sub change_entry {
327   change_swentry(create_swentry(@_));
328 }
329
330 sub create_swentryh ($) {
331   my $h = shift;
332   create_swentry(@$h{@hentry_fields});
333 }
334
335 sub change_entryh ($) {
336   change_swentry(create_swentryh(shift));
337 }
338
339 # Massage entries into the same order as WindowPos_set:
340 sub 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
347 sub 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
354 my @SWP_keys = ( [qw(width height)],    # SWP_SIZE=1
355                  [qw(x y)],             # SWP_MOVE=2
356                  [qw(behind)] );        # SWP_ZORDER=3
357 my %SWP_def;
358 @SWP_def{ map @$_, @SWP_keys }  = (0) x 20;
359
360 # Get them from a hash
361 sub 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
384 sub 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
394 sub 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
404 sub 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
415 sub ClipbrdText (@) {
416   my $morph = OS2::localMorphPM->new(0);
417   OpenClipbrd();
418   my $txt = unpack 'p', pack 'L', ClipbrdData @_;
419   CloseClipbrd();
420   $txt;
421 }
422
423 sub 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
432 sub 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
439 my %pointers;
440
441 sub 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.
450 sub 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.
463 sub 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]]
492 sub 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;
511 sub 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
523 my @vioConfig = qw(adapter display cbMemory Configuration VDHVersion Flags
524                    HWBufferSize FullSaveSize PartSaveSize EMAdapters EMDisplays);
525
526 sub 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;
534 sub vioMode() {unpack 'x[S]CCSSSSCCLLLLL', _vioMode}
535
536 my @vioMode = qw( fbType color col row hres vres fmt_ID attrib buf_addr
537                   buf_length full_length partial_length ext_data_addr);
538
539 sub viohMode() {
540   my %h;
541   @h{@vioMode} = vioMode;
542   %h;
543 }
544
545 sub 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
552 sub kbdChar (;$$) {unpack 'CCCCSL', &_kbdChar}
553
554 my @kbdChar = qw(ascii scancode status nlsstate shifts time);
555 sub kbdhChar (;$$) {
556   my %h;
557   @h{@kbdChar} = &kbdChar;
558   %h
559 }
560
561 sub kbdStatus (;$) {unpack 'x[S]SSSS', &_kbdStatus}
562 my @kbdStatus = qw(state turnChar intCharFlags shifts);
563 sub kbdhStatus (;$) {
564   my %h;
565   @h{@kbdStatus} = &kbdStatus;
566   %h
567 }
568 sub 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
579 1;
580 __END__
581
582 =head1 NAME
583
584 OS2::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
595 the builtin function system() under OS/2 allows an optional first
596 argument which denotes the mode of the process. Note that this argument is
597 recognized only if it is strictly numerical.
598
599 You 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
607 and 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
626 On OS/2 processes have the usual I<parent/child> semantic;
627 additionally, there is a hierarchy of sessions with their own
628 I<parent/child> tree.  A session is either a FS session, or a windowed
629 pseudo-session created by PM.  A session is a "unit of user
630 interaction", a change to in/out settings in one of them does not
631 affect other sessions.
632
633 =over
634
635 =item my_type()
636
637 returns 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
642 returns the type of the executable file C<file>, or
643 dies 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
649 Application type is not specified in the executable header.
650
651 =item C<T_NOTWINDOWCOMPAT> (1)
652
653 Application type is not-window-compatible.
654
655 =item C<T_WINDOWCOMPAT> (2)
656
657 Application type is window-compatible.
658
659 =item C<T_WINDOWAPI> (3)
660
661 Application type is window-API.
662
663 =back
664
665 The remaining bits should be masked with the following values to
666 determine the type of the executable:
667
668 =over
669
670 =item C<T_BOUND> (8)
671
672 Set to 1 if the executable file has been "bound" (by the BIND command)
673 as a Family API application. Bits 0, 1, and 2 still apply.
674
675 =item C<T_DLL> (0x10)
676
677 Set to 1 if the executable file is a dynamic link library (DLL)
678 module. Bits 0, 1, 2, 3, and 5 will be set to 0.
679
680 =item C<T_DOS> (0x20)
681
682 Set to 1 if the executable file is in PC/DOS format. Bits 0, 1, 2, 3,
683 and 4 will be set to 0.
684
685 =item C<T_PHYSDRV> (0x40)
686
687 Set to 1 if the executable file is a physical device driver.
688
689 =item C<T_VIRTDRV> (0x80)
690
691 Set to 1 if the executable file is a virtual device driver.
692
693 =item C<T_PROTDLL> (0x100)
694
695 Set to 1 if the executable file is a protected-memory dynamic link
696 library module.
697
698 =item C<T_32BIT> (0x4000)
699
700 Set to 1 for 32-bit executable files.
701
702 =back
703
704 file_type() may croak with one of the strings C<"Invalid EXE
705 signature"> or C<"EXE marked invalid"> to indicate typical error
706 conditions.  If given non-absolute path, will look on C<PATH>, will
707 add extension F<.exe> if no extension is present (add extension F<.>
708 to suppress).
709
710 =item C<@list = process_codepages()>
711
712 the first element is the currently active codepage, up to 2 additional
713 entries specify the system's "prepared codepages": the codepages the
714 user can switch to.  The active codepage of a process is one of the
715 prepared codepages of the system (if present).
716
717 =item C<process_codepage_set($cp)>
718
719 sets the currently active codepage.  [Affects printer output, in/out
720 codepages of sessions started by this process, and the default
721 codepage for drawing in PM; is inherited by kids.  Does not affect the
722 out- and in-codepages of the session.]
723
724 =item ppid()
725
726 returns the PID of the parent process.
727
728 =item C<ppidOf($pid = $$)>
729
730 returns the PID of the parent process of $pid.  -1 on error.
731
732 =item C<sidOf($pid = $$)>
733
734 returns the session id of the process id $pid.  -1 on error.
735
736 =back
737
738 =head2 Control of VIO sessions
739
740 VIO applications are applications running in a text-mode session.
741
742 =over
743
744 =item out_codepage()
745
746 gets code page used for screen output (glyphs).  -1 means that a user font
747 was loaded.
748
749 =item C<out_codepage_set($cp)>
750
751 sets code page used for screen output (glyphs).  -1 switches to a preloaded
752 user font.  -2 switches off the preloaded user font.
753
754 =item in_codepage()
755
756 gets code page used for keyboard input.  0 means that a hardware codepage
757 is used.
758
759 =item C<in_codepage_set($cp)>
760
761 sets code page used for keyboard input.
762
763 =item C<($w, $h) = scrsize()>
764
765 width and height of the given console window in character cells.
766
767 =item C<scrsize_set([$w, ] $h)>
768
769 set height (and optionally width) of the given console window in
770 character cells.  Use 0 size to keep the old size.
771
772 =item C<($s, $e, $w, $a) = cursor()>
773
774 gets 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
776 values mean visible, in graphic modes color).
777
778 =item C<cursor_set($s, $e, [$w [, $a]])>
779
780 sets start/end lines of the blinking cursor in the charcell.  Negative
781 values mean percents of the character cell height.
782
783 =item screen()
784
785 gets a buffer with characters and attributes of the screen.
786
787 =item C<screen_set($buffer)>
788
789 restores the screen given the result of screen().  E.g., if the file
790 C<$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
800 will restore the screen content even if the height of the window
801 changed (if the width changed, more manipulation is needed).
802
803 =back
804
805 =head2 Control of the process list
806
807 With the exception of Title_set(), all these calls require that PM is
808 running, they would not work under alternative Session Managers.
809
810 =over
811
812 =item process_entry()
813
814 returns a list of the following data:
815
816 =over
817
818 =item
819
820 Title of the process (in the C<Ctrl-Esc> list);
821
822 =item
823
824 window handle of switch entry of the process (in the C<Ctrl-Esc> list);
825
826 =item
827
828 window handle of the icon of the process;
829
830 =item
831
832 process handle of the owner of the entry in C<Ctrl-Esc> list;
833
834 =item
835
836 process id of the owner of the entry in C<Ctrl-Esc> list;
837
838 =item
839
840 session id of the owner of the entry in C<Ctrl-Esc> list;
841
842 =item
843
844 whether visible in C<Ctrl-Esc> list;
845
846 =item
847
848 whether item cannot be switched to (note that it is not actually
849 grayed in the C<Ctrl-Esc> list));
850
851 =item
852
853 whether participates in jump sequence;
854
855 =item
856
857 program 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
866 Although there are several other program types for WIN-OS/2 programs,
867 these do not show up in this field. Instead, the PROG_VDM or
868 PROG_WINDOWEDVDM program types are used. For instance, for
869 PROG_31_STDSEAMLESSVDM, PROG_WINDOWEDVDM is used. This is because all
870 the WIN-OS/2 programs run in DOS sessions. For example, if a program
871 is a windowed WIN-OS/2 program, it runs in a PROG_WINDOWEDVDM
872 session. Likewise, if it's a full-screen WIN-OS/2 program, it runs in
873 a PROG_VDM session.
874
875 =item
876
877 switch-entry handle.
878
879 =back
880
881 Optional arguments: the pid and the window-handle of the application running
882 in the OS/2 session to query.
883
884 =item process_hentry()
885
886 similar 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
895 similar to process_entry(), but returns a list of array reference for all
896 the elements in the switch list (one controlling C<Ctrl-Esc> window).
897
898 =item process_hentries()
899
900 similar to process_hentry(), but returns a list of hash reference for all
901 the elements in the switch list (one controlling C<Ctrl-Esc> window).
902
903 =item change_entry()
904
905 changes a process entry, arguments are the same as process_entry() returns.
906
907 =item change_entryh()
908
909 Similar to change_entry(), but takes a hash reference as an argument.
910
911 =item process_hwnd()
912
913 returns the C<owner_hwnd> of the process entry (for VIO windowed processes
914 this is the frame window of the session).
915
916 =item Title()
917
918 returns 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
920 implementation is a shortcut via process_entry().)
921
922 =item C<Title_set(newtitle)>
923
924 tries two different interfaces.  The Session Manager one does not work
925 with some windows (if the title is set from the start).
926 This is a limitation of OS/2, in such a case $^E is set to 372 (type
927
928   help 372
929
930 for a funny - and wrong  - explanation ;-).  In such cases a
931 direct-manipulation of low-level entries is used (same as bothTitle_set()).
932 Keep in mind that some versions of OS/2 leak memory with such a manipulation.
933
934 =item winTitle()
935
936 returns text of the titlebar of the current process' window.
937
938 =item C<winTitle_set(newtitle)>
939
940 sets text of the titlebar of the current process' window.  The change does not
941 affect the text of the switch entry of the current window.
942
943 =item C<swTitle_set(newtitle)>
944
945 sets text of the task switch menu entry of the current process' window.  [There
946 is no API to query this title.]  Does it via SwitchEntry interface,
947 not Session manager interface.  The change does not affect the text of the
948 titlebar of the current window.
949
950 =item C<bothTitle_set(newtitle)>
951
952 sets text of the titlebar and task switch menu of the current process' window
953 via direct manipulation of the windows' texts.
954
955 =item C<SwitchToProgram([$sw_entry])>
956
957 switch to session given by a switch list handle (defaults to the entry of our process).
958
959 Use of this function causes another window (and its related windows)
960 of a PM session to appear on the front of the screen, or a switch to
961 another session in the case of a non-PM program. In either case,
962 the keyboard (and mouse for the non-PM case) input is directed to
963 the new program.
964
965 =back
966
967 =head2 Control of the PM windows
968
969 Some of these API's require sending a message to the specified window.
970 In such a case the process needs to be a PM process, or to be morphed
971 to a PM process via OS2::MorphPM().
972
973 For a temporary morphing to PM use L<OS2::localMorphPM class>.
974
975 Keep in mind that PM windows are engaged in 2 "orthogonal" window
976 trees, as well as in the z-order list.
977
978 One tree is given by the I<parent/child> relationship.  This
979 relationship affects drawing (child is drawn relative to its parent
980 (lower-left corner), and the drawing is clipped by the parent's
981 boundary; parent may request that I<it's> drawing is clipped to be
982 confined to the outsize of the childs and/or siblings' windows);
983 hiding; minimizing/restoring; and destroying windows.
984
985 Another tree (not necessarily connected?) is given by I<ownership>
986 relationship.  Ownership relationship assumes cooperation of the
987 engaged windows via passing messages on "important events"; e.g.,
988 scrollbars send information messages when the "bar" is moved, menus
989 send messages when an item is selected; frames
990 move/hide/unhide/minimize/restore/change-z-order-of owned frames when
991 the owner is moved/etc., and destroy the owned frames (even when these
992 frames are not descendants) when the owner is destroyed; etc.  [An
993 important restriction on ownership is that owner should be created by
994 the same thread as the owned thread, so they engage in the same
995 message queue.]
996
997 Windows may be in many different state: Focused (take keyboard events) or not,
998 Activated (=Frame windows in the I<parent/child> tree between the root and
999 the window with the focus; usually indicate such "active state" by titlebar
1000 highlights, and take mouse events) or not, Enabled/Disabled (this influences
1001 the ability to update the graphic, and may change appearance, as for 
1002 enabled/disabled buttons), Visible/Hidden, Minimized/Maximized/Restored, Modal
1003 or not, etc.
1004
1005 The APIs below all die() on error with the message being $^E.
1006
1007 =over
1008
1009 =item C<WindowText($hwnd)>
1010
1011 gets "a text content" of a window.  Requires (morphing to) PM.
1012
1013 =item C<WindowText_set($hwnd, $text)>
1014
1015 sets "a text content" of a window.  Requires (morphing to) PM.
1016
1017 =item C<($x, $y, $flags, $width, $height, $behind, @rest) = WindowPos($hwnd)>
1018
1019 gets window position info as 8 integers (of C<SWP>), in the order suitable
1020 for WindowPos_set().  @rest is marked as "reserved" in PM docs.  $flags
1021 is a combination of C<SWP_*> constants.
1022
1023 =item C<$hash = hWindowPos($hwnd)>
1024
1025 gets window position info as a hash reference; the keys are C<flags width
1026 height x y behind hwnd reserved1 reserved2>.
1027
1028 Example:
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
1034 Set state of the window: position, size, zorder, show/hide, activation,
1035 minimize/maximize/restore etc.  Which of these operations to perform
1036 is governed by $flags.
1037
1038 =item C<hWindowPos_set($hash, [$hwnd])>
1039
1040 Same as C<WindowPos_set>, but takes the position from keys C<fl width height
1041 x y behind hwnd> of the hash referenced by $hash.  If $hwnd is explicitly
1042 specified, it overrides C<$hash->{hwnd}>.  If $hash->{flags} is not specified,
1043 it is calculated basing on the existing keys of $hash.  Requires (morphing to) PM.
1044
1045 Example:
1046
1047   hWindowPos_set {flags => SWP_MAXIMIZE}, $hwnd; # Maximize
1048
1049 =item C<($pid, $tid) = WindowProcess($hwnd)>
1050
1051 gets I<PID> and I<TID> of the process associated to the window.
1052
1053 =item C<ClassName($hwnd)>
1054
1055 returns the class name of the window.
1056
1057 If this window is of any of the preregistered WC_* classes the class
1058 name returned is in the form "#nnnnn", where "nnnnn" is a group
1059 of up to five digits that corresponds to the value of the WC_* class name
1060 constant.
1061
1062 =item FocusWindow()
1063
1064 returns the handle of the focus window.  Optional argument for specifying
1065 the desktop to use.
1066
1067 =item C<FocusWindow_set($hwnd)>
1068
1069 set the focus window by handle.  Optional argument for specifying the desktop
1070 to use.  E.g, the first entry in program_entries() is the C<Ctrl-Esc> list.
1071 To 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
1080 Switching focus to currently-unfocused window moves the window to the
1081 front in Z-order; use FocusWindow_set_keep_Zorder() to avoid this.
1082
1083 =item C<FocusWindow_set_keep_Zorder($hwnd)>
1084
1085 same as FocusWindow_set(), but preserves the Z-order of windows.
1086
1087 =item C<ActiveWindow([$parentHwnd])>
1088
1089 gets the active subwindow's handle for $parentHwnd or desktop.
1090 Returns FALSE if none.
1091
1092 =item C<ActiveWindow_set($hwnd, [$parentHwnd])>
1093
1094 sets the active subwindow's handle for $parentHwnd or desktop.  Requires (morphing to) PM.
1095
1096 =item C<ShowWindow($hwnd [, $show])>
1097
1098 Set visible/hidden flag of the window.  Default: $show is TRUE.
1099
1100 =item C<EnableWindowUpdate($hwnd [, $update])>
1101
1102 Set window visibility state flag for the window for subsequent drawing.
1103 No actual drawing is done at this moment.  Use C<ShowWindow($hwnd, $state)>
1104 when redrawing is needed.  While update is disabled, changes to the "window
1105 state" 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
1111 Set the window enabled state.  Default: $enable is TRUE.
1112
1113 Results in C<WM_ENABLED> message sent to the window.  Typically, this
1114 would change the appearence of the window.  If at the moment of disabling
1115 focus is in the window (or a descendant), focus is lost (no focus anywhere).
1116 If focus is needed, it can be reassigned explicitly later.
1117
1118 =item IsWindowEnabled(), IsWindowVisible(), IsWindowShowing()
1119
1120 these functions take $hwnd as an argument.  IsWindowEnabled() queries
1121 the state changed by EnableWindow(), IsWindowVisible() the state changed
1122 by ShowWindow(), IsWindowShowing() is true if there is a part of the window
1123 visible on the screen.
1124
1125 =item C<PostMsg($hwnd, $msg, $mp1, $mp2)>
1126
1127 post message to a window.  The meaning of $mp1, $mp2 is specific for each
1128 message 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
1150 In fact, MPFROMSHORT() may be omitted above.
1151
1152 For messages to other processes, messages which take/return a pointer are
1153 not supported.
1154
1155 =item C<MP*()>
1156
1157 The functions MPFROMSHORT(), MPVOID(), MPFROMCHAR(), MPFROM2SHORT(),
1158 MPFROMSH2CH(), MPFROMLONG() can be used the same way as from C.  Use them
1159 to construct parameters $m1, $m2 to PostMsg().
1160
1161 These functions are not exported by default.
1162
1163 =item C<$eh = BeginEnumWindows($hwnd)>
1164
1165 starts enumerating immediate child windows of $hwnd in z-order.  The
1166 enumeration reflects the state at the moment of BeginEnumWindows() calls;
1167 use IsWindow() to be sure.  All the functions in this group require (morphing to) PM.
1168
1169 =item C<$kid_hwnd = GetNextWindow($eh)>
1170
1171 gets the next kid in the list.  Gets 0 on error or when the list ends.
1172
1173 =item C<EndEnumWindows($eh)>
1174
1175 End enumeration and release the list.
1176
1177 =item C<@list = ChildWindows([$hwnd])>
1178
1179 returns the list of child windows at the moment of the call.  Same remark
1180 as for enumeration interface applies.  Defaults to HWND_DESKTOP.
1181 Example 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
1192 true if the window handle is still valid.
1193
1194 =item C<QueryWindow($hwnd, $type)>
1195
1196 gets the handle of a related window.  $type should be one of C<QW_*> constants.
1197
1198 =item C<IsChild($hwnd, $parent)>
1199
1200 return TRUE if $hwnd is a descendant of $parent.
1201
1202 =item C<WindowFromId($hwnd, $id)>
1203
1204 return 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
1213 gets 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,
1216 or 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
1222 gets a dialog item window handle for an item of type $type of $dlgHwnd
1223 relative to $relativeHwnd, which is descendant of $dlgHwnd.
1224 $relativeHwnd may be specified if $type is EDI_FIRSTTABITEM or
1225 EDI_LASTTABITEM.
1226
1227 The return is always an immediate child of hwndDlg, even if hwnd is
1228 not an immediate child window.  $type may be
1229
1230 =over
1231
1232 =item EDI_FIRSTGROUPITEM
1233
1234 First item in the same group.
1235
1236 =item EDI_FIRSTTABITEM
1237
1238 First item in dialog with style WS_TABSTOP. hwnd is ignored.
1239
1240 =item EDI_LASTGROUPITEM
1241
1242 Last item in the same group.
1243
1244 =item EDI_LASTTABITEM
1245
1246 Last item in dialog with style WS_TABSTOP. hwnd is ignored.
1247
1248 =item EDI_NEXTGROUPITEM
1249
1250 Next item in the same group. Wraps around to beginning of group when
1251 the end of the group is reached.
1252
1253 =item EDI_NEXTTABITEM
1254
1255 Next item with style WS_TABSTOP. Wraps around to beginning of dialog
1256 item list when end is reached.
1257
1258 =item EDI_PREVGROUPITEM
1259
1260 Previous item in the same group. Wraps around to end of group when the
1261 start of the group is reached. For information on the WS_GROUP style,
1262 see Window Styles.
1263
1264 =item EDI_PREVTABITEM
1265
1266 Previous item with style WS_TABSTOP. Wraps around to end of dialog
1267 item list when beginning is reached.
1268
1269 =back
1270
1271 =item DesktopWindow()
1272
1273 gets the actual window handle of the PM desktop; most APIs accept the
1274 pseudo-handle C<HWND_DESKTOP> instead.  Keep in mind that the WPS
1275 desktop (one with WindowText() being C<"Desktop">) is a different beast?!
1276
1277 =item TopLevel($hwnd)
1278
1279 gets the toplevel window of $hwnd.
1280
1281 =item ResetWinError()
1282
1283 Resets $^E.  One may need to call it before the C<Win*>-class APIs which may
1284 return 0 during normal operation.  In such a case one should check both
1285 for return value being zero and $^E being non-zero.  The following APIs
1286 do ResetWinError() themselves, thus do not need an explicit one:
1287
1288   WindowPtr
1289   WindowULong
1290   WindowUShort
1291   WindowTextLength
1292   ActiveWindow
1293   PostMsg
1294
1295 This 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
1305 gets the path of the directory which corresponds to Desktop.
1306
1307 =item ClipbrdText()
1308
1309 gets the content of the clipboard.  An optional argument is the format
1310 of the data in the clipboard (defaults to C<CF_TEXT>).
1311
1312 Note that the usual convention is to have clipboard data with
1313 C<"\r\n"> as line separators.
1314
1315 =item ClipbrdText_set($txt)
1316
1317 sets the text content of the clipboard.  Unless the optional argument
1318 is TRUE, will convert newlines to C<"\r\n">.  Another optional
1319 argument is the format of the data in the clipboard (defaults to
1320 C<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
1366 Low-level methods to access clipboard and the atom table(s).
1367
1368 =back
1369
1370 =head1 OS2::localMorphPM class
1371
1372 This 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
1379 The argument has the same meaning as one to OS2::MorphPM().  Calls can
1380 nest with internal ones being NOPs.
1381
1382 =head1 TODO
1383
1384 Add 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
1411 Document and test: Query/SetWindowULong/Short/Ptr, SetWindowBits.
1412 InvalidateRect, CreateFrameControl, ClipbrdFmtInfo ClipbrdOwner
1413 ClipbrdViewer ClipbrdData OpenClipbrd CloseClipbrd ClipbrdData_set
1414 ClipbrdOwner_set ClipbrdViewer_set EnumClipbrdFmts EmptyClipbrd
1415 AddAtom FindAtom DeleteAtom AtomUsage AtomName AtomLength
1416 SystemAtomTable CreateAtomTable DestroyAtomTable
1417
1418 Implement 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
1578 Why C<hWindowPos DesktopWindow> gives C<< behind => HWND_TOP >>?
1579
1580 =head1 $^E
1581
1582 the majority of the APIs of this module set $^E on failure (no matter
1583 whether they die() on failure or not).  By the semantic of PM API
1584 which returns something other than a boolean, it is impossible to
1585 distinguish failure from a "normal" 0-return.  In such cases C<$^E ==
1586 0> indicates an absence of error.
1587
1588 =head1 EXPORTS
1589
1590 In addition to symbols described above, the following constants (available
1591 also via module C<OS2::Process::Const>) are exportable.  Note that these
1592 symbols live in package C<OS2::Process::Const>, they are not available
1593 by 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
1621 whether a given API dies or returns FALSE/empty-list on error may be
1622 confusing.  This may change in the future.
1623
1624 =head1 AUTHOR
1625
1626 Andreas Kaiser <ak@ananke.s.bawue.de>,
1627 Ilya Zakharevich <ilya@math.ohio-state.edu>.
1628
1629 =head1 SEE ALSO
1630
1631 C<spawn*>() system calls, L<OS2::Proc> and L<OS2::WinObject> modules.
1632
1633 =cut