DBA Data[Home] [Help]

PACKAGE BODY: APPS.XNP_WSGL

Source


1 package body XNP_wsgl as
2 /* $Header: XNPWSGLB.pls 120.1 2005/06/24 05:59:29 appldev ship $ */
3 
4 
5 -- Current version of WSGL
6    WSGL_VERSION constant varchar2(30) := '2.0.20.2.0';
7 
8 --------------------------------------------------------------------------------
9 -- Define types for pl/sql tables of number(10), varchar(20) and boolean
10 -- for use internally in layout
11    type typNumberTable   is table of number(10)
12                          index by binary_integer;
13 
14    type typString20Table is table of varchar2(20)
15                          index by binary_integer;
16 
17    type typBooleanTable  is table of boolean
18                          index by binary_integer;
19 
20 --------------------------------------------------------------------------------
21 
22 --------------------------------------------------------------------------------
23 --
24 -- Define the features and subfeatures tables for browsers
25 --
26 --
27 
28 type featuresRecT is record
29 (
30    browser   varchar2 (50),
31    feature   varchar2 (50),
32    supported boolean
33 );
34 
35 type featuresTableT is table of featuresRecT index by binary_integer;
36 
37 featuresTable featuresTableT;
38 
39 --------------------------------------------------------------------------------
40 -- Define Layout variables.  These retain their value only for the
41 -- duration of the creation of a single page.
42    LayNumOfCols       number(3) := 0;
43    LayCurrentCol      number(3) := 0;
44    LayColumnWidths    typNumberTable;
45    LayColumnAlign     typString20Table;
46    LayPageCenter      typBooleanTable;
47    LayOutputLine      Long;
48    LayPaddedText      Long;
49    LayDataSegment     Long;
50    LayEmptyLine       boolean := TRUE;
51    LayActionCreated   boolean := FALSE;
52    LayStyle           number(1) := LAYOUT_TABLE;
53    LayBorderTable     boolean := FALSE;
54    LayVertBorderChars varchar2(4);
55    LayHoriBorderChars varchar2(2000);
56    LayCustomBullet    varchar2(256) := '';
57    LayNumberOfPages   number(2) := 0;
58    LayNumberOfRLButs  number(2) := 0;
59    LayMenuLevel       number(3) := -1;
60    LayInBottomFrame   boolean := false;
61 --------------------------------------------------------------------------------
62 
63 --------------------------------------------------------------------------------
64 -- Define variable to hold URL currently being built.
65    CurrentURL   varchar2(2000);
66    URLComplete  boolean := false;
67    URLCookieSet boolean := false;
68 --------------------------------------------------------------------------------
69 
70 --------------------------------------------------------------------------------
71 -- Declare private procedure for padding preformatted text
72    procedure LayoutPadTextToLength(p_text in OUT NOCOPY varchar2,
73                                    p_length in number,
74                                    p_align in varchar2);
75 --------------------------------------------------------------------------------
76 
77 --------------------------------------------------------------------------------
78 -- Declare private procedure for where clause predicates
79    function BuildWherePredicate(p_field1   in varchar2,
80                                 p_field2   in varchar2,
81                                 p_sli      in varchar2,
82                                 p_datatype in number,
83                                 p_where    in OUT NOCOPY varchar2,
84                                 p_date_format in varchar2,
85                                 p_caseinsensitive in boolean) return varchar2;
86    function CaseInsensitivePredicate(p_sli in varchar2,
87                                      p_field in varchar2,
88                                      p_operator in varchar2) return varchar2;
89 --------------------------------------------------------------------------------
90 
91 
92 --------------------------------------------------------------------------------
93 -- Name:        Info
94 --
95 -- Description: Display information about WSGL.  Useful for debugging purposes.
96 --
97 -- Parameters:  p_full is a full list reequired (no if called from About)
98 --              p_app  name of application system
99 --              p_mod  name of module
100 --
101 --------------------------------------------------------------------------------
102 procedure Info(p_full in boolean default true,
103                p_app in varchar2 default null,
104                p_mod in varchar2 default null) is
105    cursor c1 is
106       select product, version, status
107       from   product_component_version
108       where  upper(product) like '%ORACLE%SERVER%'
109       or     upper(product) like '%PL/SQL%'
110       order  by product;
111    current_user varchar2(30) := GetUser;
112 begin
113    if p_full then
114       DefinePageHead(MsgGetText(101,XNP_WSGLM.DSP101_WSGL_INFO));
115       OpenPageBody;
116       DefaultPageCaption(MsgGetText(101,XNP_WSGLM.DSP101_WSGL_INFO));
117    end if;
118    LayoutOpen(LAYOUT_TABLE, TRUE);
119    LayoutRowStart;
120    LayoutHeader(50, 'LEFT', NULL);
121    LayoutHeader(50, 'LEFT', NULL);
122    LayoutRowEnd;
123    LayoutRowStart;
124    LayoutData(MsgGetText(102,XNP_WSGLM.DSP102_WSGL));
125    LayoutData(WSGL_VERSION);
126    LayoutRowEnd;
127    LayoutRowStart;
128    LayoutData(MsgGetText(103,XNP_WSGLM.DSP103_USER));
129    LayoutData(current_user);
130    LayoutRowEnd;
131    for c1rec in c1 loop
132       LayoutRowStart;
133       LayoutData(c1rec.product);
134       LayoutData(c1rec.version||' '||c1rec.status);
135       LayoutRowEnd;
136    end loop;
137    if not p_full then
138       LayoutRowStart;
139       LayoutData(MsgGetText(105,XNP_WSGLM.DSP105_WEB_SERVER));
140       LayoutData(owa_util.get_cgi_env('SERVER_SOFTWARE'));
141       LayoutRowEnd;
142       LayoutRowStart;
143       LayoutData(MsgGetText(106,XNP_WSGLM.DSP106_WEB_BROWSER));
144       LayoutData(owa_util.get_cgi_env('HTTP_USER_AGENT'));
145       LayoutRowEnd;
146       LayoutRowStart;
147       LayoutData(MsgGetText(125,XNP_WSGLM.DSP125_REPOS_APPSYS));
148       LayoutData(p_app);
149       LayoutRowEnd;
150       LayoutRowStart;
151       LayoutData(MsgGetText(126,XNP_WSGLM.DSP126_REPOS_MODULE));
152       LayoutData(p_mod);
153       LayoutRowEnd;
154    end if;
155    LayoutClose;
156    if p_full then
157       htp.header(LayNumberOfPages, MsgGetText(104,XNP_WSGLM.DSP104_ENVIRONMENT));
158       owa_util.print_cgi_env;
159       ClosePageBody;
160    end if;
161 exception
162    when others then
163       raise_application_error(-20000, 'XNP_WSGL.Info<br>'||SQLERRM);
164 end;
165 
166 --------------------------------------------------------------------------------
167 -- Name:        IsSupported
168 --
169 -- Description: Maps HTML and Javascript features to browsers to determine if
170 --              the browser being used supports a given feature or subfeature
171 --
172 -- Parameters:  feature    IN the main feature we want to know if the browser
173 --                            supports
174 --------------------------------------------------------------------------------
175 
176 function IsSupported (feature in varchar2) return boolean is
177 
178   browser        varchar2(2000) := owa_util.get_cgi_env ('HTTP_USER_AGENT');
179   featureSupport boolean        := True;
180 
181 begin
182 
183   -- Browser string must be unique
184 
185   featuresTable (1).browser   := 'MOZILLA/2.__%';
186   featuresTable (1).feature   := 'NOSCRIPT';
187   featuresTable (1).supported := False;
188 
189   -- Search the features table for a matching entry
190 
191   for i in 1..featuresTable.count
192   loop
193 
194     if (upper (browser) like upper (featuresTable (i).browser)) and
195        (upper (feature) =    upper (featuresTable (i).feature))
196     then
197 
198       featureSupport := featuresTable (i).supported;
199 
200     end if;
201 
202   end loop;
203 
204   return featureSupport;
205 
206 end IsSupported;
207 
208 --------------------------------------------------------------------------------
209 -- Name:        LayoutOpen
210 --
211 -- Description: This procedure is used to set up information which will
212 --              control how data/fields are layed out in the generated
213 --              pages.  A number of layout styles are supported, defined
214 --              by the constants LAYOUT_TABLE, LAYOUT_BULLET etc
215 --
216 -- Parameters:  p_layout_style   IN  The layout style
217 --              p_border         IN  If layout style is TABLE, should the
218 --                                   table have a border
219 --              p_custom_bullet  IN  If the layout style is CUSTOM, the
220 --                                   expression to use as the custom bullet
221 --------------------------------------------------------------------------------
222 procedure LayoutOpen(p_layout_style in number,
223                      p_border in boolean,
224                      p_custom_bullet in varchar2) is
225 begin
226    -- Initialise the layout parameters
227 
228    LayStyle := p_layout_style;
229    LayCustomBullet := p_custom_bullet;
230    LayBorderTable := p_border;
231    LayVertBorderChars := ' ';
232    LayHoriBorderChars := NULL;
233    LayNumOfCols := 0;
234    LayCurrentCol := 0;
235    if (LayStyle = LAYOUT_BULLET)
236    then
237       -- Open List
238       htp.ulistOpen;
239    elsif (LayStyle = LAYOUT_NUMBER)
240    then
241       -- Open List
242       htp.olistOpen;
243    elsif (LayStyle = LAYOUT_TABLE)
244    then
245       -- If tables are requested, check that the current browser
246       -- supports them, if not, default to PREFORMAT
247       if (TablesSupported) then
248          htp.para;
249          -- Open Table
250          if (p_border) then
251 
252             htp.tableOpen('BORDER');
253          else
254             htp.tableOpen;
255          end if;
256       else
257          LayoutOpen(LAYOUT_PREFORMAT, p_border, p_custom_bullet);
258       end if;
259    elsif (LayStyle = LAYOUT_PREFORMAT)
260    then
261       -- Open Preformat
262       htp.preOpen;
263       if (p_border) then
264          LayVertBorderChars := '|';
265       end if;
266    else
267       -- Start a new paragraph if WRAP
268       htp.para;
269    end if;
270 exception
271    when others then
272       raise_application_error(-20000, 'XNP_WSGL.LayoutOpen<br>'||SQLERRM);
273 end;
274 
275 --------------------------------------------------------------------------------
276 -- Name:        LayoutClose
277 --
278 -- Description: End the layout area.
279 --
280 -- Parameters:  None
281 --
282 --------------------------------------------------------------------------------
283 procedure LayoutClose is
284 begin
285    if LayCurrentCol <> LayNumOfCols then
286       LayCurrentCol := LayNumOfCols;
287       LayoutRowEnd;
288    end if;
289    if (LayStyle = LAYOUT_BULLET)
290    then
291       htp.ulistClose;
292    elsif (LayStyle = LAYOUT_NUMBER)
293    then
294       htp.olistClose;
295    elsif (LayStyle = LAYOUT_TABLE)
296    then
297       htp.tableClose;
298    elsif (LayStyle = LAYOUT_PREFORMAT)
299    then
300       if LayBorderTable then
301          htp.p(LayHoriBorderChars);
302       end if;
303       htp.preClose;
304    end if;
305    htp.para;
306 exception
307    when others then
308       raise_application_error(-20000, 'XNP_WSGL.LayoutClose<br>'||SQLERRM);
309 end;
310 
311 --------------------------------------------------------------------------------
312 -- Name:        LayoutRowStart
313 --
314 -- Description: Starts a 'row' in the current layout style.  This may be
315 --              a real row if it is a table, or a new list item for lists
316 --              etc.
317 --
318 --              Initialises the variable LayOutputLine which is used to
319 --              build the entire 'row' until it is printed using
320 --              LayoutRowEnd().
321 --
322 -- Parameters:  p_valign  IN   The verical alignment of the row if TABLE
323 --
324 --------------------------------------------------------------------------------
325 procedure LayoutRowStart(p_valign in varchar2) is
326 begin
327    if LayCurrentCol <> LayNumOfCols then
328       return;
329    end if;
330    LayCurrentCol := 0;
331    LayEmptyLine := TRUE;
332    if (LayStyle = LAYOUT_BULLET) or
333       (LayStyle = LAYOUT_NUMBER)
334    then
335       -- Add list item marker
336       LayOutputLine :=  htf.ListItem;
337    elsif (LayStyle = LAYOUT_CUSTOM)
338    then
339       -- Add the Custom Bullet
340       LayOutputLine := LayCustomBullet || ' ';
341    elsif (LayStyle = LAYOUT_TABLE)
342    then
343       -- Start a new row
344       LayOutputLine := htf.tableRowOpen(cvalign=>p_valign);
345    elsif (LayStyle = LAYOUT_PREFORMAT)
346    then
347       LayOutputLine := LayVertBorderChars;
348    end if;
349 exception
350    when others then
351       raise_application_error(-20000, 'XNP_WSGL.LayoutRowStart<br>'||SQLERRM);
352 end;
353 
354 --------------------------------------------------------------------------------
355 -- Name:        LayoutRowEnd
356 --
357 -- Description: If anything in the current row, it is output using htp.p()
358 --              procedure, and then LayOutputLine is cleared.
359 --
360 -- Parameters:  None
361 --
362 --------------------------------------------------------------------------------
363 procedure LayoutRowEnd is
364    l_loop number(4) := 0;
365 begin
366    if LayCurrentCol <> LayNumOfCols then
367       return;
368    end if;
369    if not LayEmptyLine
370    then
371       if (LayStyle = LAYOUT_BULLET) or
372          (LayStyle = LAYOUT_NUMBER)
373       then
374          htp.p(LayOutputLine);
375       elsif (LayStyle = LAYOUT_CUSTOM)
376       then
377          htp.p(LayOutputLine);
378          htp.nl;
379       elsif (LayStyle = LAYOUT_TABLE)
380       then
381          htp.p(LayOutputLine || htf.tableRowClose);
382       else
383          if LayStyle = LAYOUT_PREFORMAT and LayBorderTable then
384             if LayHoriBorderChars is null then
385                LayHoriBorderChars := '-';
386                for l_loop in 1..LayNumOfCols loop
387                  LayHoriBorderChars := LayHoriBorderChars || rpad('-', LayColumnWidths(l_loop) + 1, '-');
388                end loop;
389             end if;
390             htp.p(LayHoriBorderChars);
391          end if;
392          htp.p(LayOutputLine);
393 
394       end if;
395    end if;
396    LayOutputLine := '';
397 exception
398    when others then
399       raise_application_error(-20000, 'XNP_WSGL.LayoutRowEnd<br>'||SQLERRM);
400 end;
401 
402 --------------------------------------------------------------------------------
403 -- Name:        LayoutHeader
404 --
405 -- Description: This is used when layout style is TABLE or PREFORMAT and
406 --              defines the 'Columns' of the table.  Each has a width
407 --              (not used for TABLE), an alignment and a title.  The pl/sql
408 --              tables LayColumnWidths and LayColumnAlign are initilaised in
409 --              order that later calls to LayoutData will be correctly
410 --              position data/fields.
411 --
412 --              This procedure has no effect when layout style is not
413 --              TABLE or PREFORMAT,
414 --
415 -- Parameters:  p_width   IN   Column width
416 --              p_align   IN   Horizontal alignment or data in this column
417 --              p_title   IN   Title, if any
418 --
419 --------------------------------------------------------------------------------
420 procedure LayoutHeader(p_width in number,
421                        p_align in varchar2,
422                        p_title in varchar2) is
423    l_width number(5);
424 begin
425    LayNumOfCols := LayNumOfCols + 1;
426    LayCurrentCol := LayNumOfCols;
427    -- Only applicable if TABLE or PREFORMAT
428    if ( (LayStyle <> LAYOUT_TABLE) and
429         (LayStyle <> LAYOUT_PREFORMAT)
430       ) then
431       return;
432    end if;
433    -- If a title is defined, check if it is longer than the width of the
434    -- data in the column, in which case PREFORMAT column would need to be
435    -- wider
436    if p_title is not null then
437       l_width := length(p_title);
438    else
439       l_width := 0;
440    end if;
441 
442    -- Record the required column width
443    if l_width > p_width then
444       LayColumnWidths(LayCurrentCol) := l_width;
445    else
446       LayColumnWidths(LayCurrentCol) := p_width;
447    end if;
448    -- Record the required column alignment
449    LayColumnAlign(LayCurrentCol) := p_align;
450    -- If TABLE, create table header
451    if (LayStyle = LAYOUT_TABLE)
452    then
453       LayOutputLine := LayOutputLine || htf.tableHeader(p_title, p_align);
454       if p_title is not null then
455          LayEmptyLine := FALSE;
456       end if;
457    -- If PREFORMAT, simulate table header
458    elsif (LayStyle = LAYOUT_PREFORMAT)
459    then
460       LayPaddedText := htf.bold(p_title);
461       LayoutPadTextToLength(LayPaddedText,
462                             LayColumnWidths(LayCurrentCol),
463                             LayColumnAlign(LayCurrentCol));
464       LayOutputLine := LayOutputLine || LayPaddedText || LayVertBorderChars;
465 
466       if p_title is not null then
467          LayEmptyLine := FALSE;
468       end if;
469    end if;
470 exception
471    when others then
472       raise_application_error(-20000, 'XNP_WSGL.LayoutHeader<br>'||SQLERRM);
473 end;
474 
475 --------------------------------------------------------------------------------
476 -- Name:        LayoutData
477 --
478 -- Description: Add the text to LayOutputLine in the current layout style,
479 --              in prepeartion for being written out by a call to
480 --              LayoutRowEnd.
481 --
482 -- Parameters:  p_text   IN   The text (or field definition etc, any html)
483 --                            to be output.
484 --
485 --------------------------------------------------------------------------------
486 procedure LayoutData(p_text in varchar2) is
487 begin
488    LayCurrentCol := LayCurrentCol + 1;
489    LayEmptyLine := FALSE;
490 
491    if (LayStyle = LAYOUT_TABLE)
492    then
493       -- Add Table data, with specified alignment
494       LayOutputLine := LayOutputLine ||
495            htf.tableData(p_text, LayColumnAlign(LayCurrentCol));
496    elsif (LayStyle = LAYOUT_PREFORMAT)
497    then
498       -- Create a copy of p_text in LayPaddedText, padded in such a way as to
499       -- be the correct width and with the correct alignment
500       LayPaddedText := nvl(p_text, ' ');
501       if (LayCurrentCol <= LayNumOfCols) then
502          LayoutPadTextToLength(LayPaddedText,
503                                LayColumnWidths(LayCurrentCol),
504                                LayColumnAlign(LayCurrentCol));
505       else
506          LayPaddedText := LayPaddedText || ' ';
507       end if;
508       LayOutputLine := LayOutputLine || LayPaddedText || LayVertBorderChars;
509    else
510       -- For styles other than TABLE and PREFORMAT, simply add the text to
511       -- LayOutputLine
512       LayOutputLine := LayOutputLine || p_text || ' ';
513    end if;
514 
515 exception
516    when others then
517       raise_application_error(-20000, 'XNP_WSGL.LayoutData<br>'||SQLERRM);
518 end;
519 
520 --------------------------------------------------------------------------------
521 -- Name:        LayoutData
522 --
523 -- Description: LayoutData overloaded with a date parameter
524 --
525 -- Parameters:  p_date   IN  The date to be displayed
526 --
527 --------------------------------------------------------------------------------
528 procedure LayoutData(p_date in date) is
529 begin
530    LayoutData(to_char(p_date));
531 exception
532    when others then
533       raise_application_error(-20000, 'XNP_WSGL.LayoutData2<br>'||SQLERRM);
534 end;
535 
536 --------------------------------------------------------------------------------
537 -- Name:        LayoutData
538 --
539 -- Description: LayoutData overloaded with a number parameter
540 
541 --
542 -- Parameters:  p_number   IN  The number to be displayed
543 --
544 --------------------------------------------------------------------------------
545 procedure LayoutData(p_number in number) is
546 begin
547    LayoutData(to_char(p_number));
548 exception
549    when others then
550       raise_application_error(-20000, 'XNP_WSGL.LayoutData3<br>'||SQLERRM);
551 end;
552 
553 --------------------------------------------------------------------------------
554 -- Name:        LayoutPadTextToLength
555 --
556 -- Description: Pads the given string to the specified length and alignment.
557 --              Anything that appears between < and > will not be counted
558 --              when determining the width because it is assumed this is
559 --              HTML tags which are not displayed.
560 --
561 -- Parameters:  p_text   IN/OUT   The text to be padded
562 --              p_length IN       The width to pad to
563 --              p_align  IN       The alignment (LEFT/CENTER/RIGHT)
564 --
565 
566 --------------------------------------------------------------------------------
567 procedure LayoutPadTextToLength(p_text in OUT NOCOPY varchar2,
568                                 p_length in number,
569                                 p_align in varchar2) is
570    l_loop   number(4) := 0;
571    l_count  number(4) := 0;
572    l_pad    number(4) := 0;
573    l_pre    varchar2(1000);
574    l_post   varchar2(1000);
575    l_ignore boolean := FALSE;
576 begin
577    for l_loop in 1..length(p_text) loop
578       if substr(p_text, l_loop, 1) = '<' then
579          l_ignore := TRUE;
580       elsif l_ignore then
581          if substr(p_text, l_loop - 1, 1) = '>' then
582             l_ignore := FALSE;
583          end if;
584       end if;
585       if (not l_ignore) then
586          l_count := l_count + 1;
587       end if;
588    end loop;
589 
590    l_pad := p_length - l_count;
591    if l_pad > 0 then
592       if p_align = 'LEFT' then
593          l_pre := '';
594          l_post := rpad(' ', l_pad);
595       elsif p_align = 'CENTER' then
596          if l_pad > 1 then
597             l_pre := rpad(' ', floor(l_pad / 2));
598             l_post := rpad(' ', ceil(l_pad / 2));
599          else
600             l_pre := '';
601             l_post := rpad(' ', l_pad);
602          end if;
603       elsif p_align = 'RIGHT' then
604          l_pre := rpad(' ', l_pad);
605          l_post := '';
606       end if;
607       p_text := l_pre || p_text || l_post;
608    end if;
609 exception
610    when others then
611       raise_application_error(-20000, 'XNP_WSGL.LayoutPadTextToLength<br>'||SQLERRM);
612 end;
613 
614 --------------------------------------------------------------------------------
615 -- Name:        DefinePageHead
616 --
617 -- Description: Short cut call of OpenPageHead and ClosePageHead
618 --
619 -- Parameters:  p_title       IN   Page Title caption
620 --      p_bottomframe IN   Is this the bottom frame ?
621 --
622 --------------------------------------------------------------------------------
623 procedure DefinePageHead(p_title in varchar2,
624                          p_bottomframe in boolean) is
625 begin
626    OpenPageHead(p_title, p_bottomframe);
627    ClosePageHead;
628 exception
629    when others then
630       raise_application_error(-20000, 'XNP_WSGL.DefinePageHead<br>'||SQLERRM);
631 end;
632 
633 --------------------------------------------------------------------------------
634 -- Name:        OpenPageHead
635 --
636 -- Description:
637 --
638 -- Parameters:  p_title       IN   Page Title caption
639 --      p_bottomframe IN   Is this the bottom frame ?
640 --
641 --------------------------------------------------------------------------------
642 procedure OpenPageHead(p_title in varchar2 default null,
643                        p_bottomframe in boolean default false) is
644 begin
645    LayNumberOfPages := LayNumberOfPages + 1;
646    LayInBottomFrame := p_bottomframe;
647 
648    if (LayNumberOfPages = 1) then
649       htp.htmlOpen;
650       htp.headOpen;
651       if p_title is not null then
652          htp.title(p_title);
653       end if;
654    end if;
655 exception
656    when others then
657       raise_application_error(-20000, 'XNP_WSGL.OpenPageHead<br>'||SQLERRM);
658 end;
659 
660 --------------------------------------------------------------------------------
661 -- Name:        ClosePageHead
662 --
663 -- Description:
664 --
665 -- Parameters:  None
666 --
667 --------------------------------------------------------------------------------
668 procedure ClosePageHead is
669 begin
670    if (LayNumberOfPages = 1) then
671       htp.headClose;
672    end if;
673 exception
674    when others then
675       raise_application_error(-20000, 'XNP_WSGL.ClosePageHead<br>'||SQLERRM);
676 end;
677 
678 --------------------------------------------------------------------------------
679 -- Name:        OpenPageBody
680 --
681 
682 -- Description:
683 --
684 -- Parameters:  p_center     IN   Center Alignment
685 --      p_attributes IN   Body attributes
686 --
687 --------------------------------------------------------------------------------
688 procedure OpenPageBody(p_center in boolean,
689                        p_attributes in varchar2) is
690   l_prev_centered boolean := FALSE;
691 begin
692    LayPageCenter(LayNumberOfPages) := p_center;
693    if (LayNumberOfPages = 1) then
694       htp.bodyOpen(cattributes=>p_attributes);
695    end if;
696    if (LayNumberOfPages > 1) then
697       l_prev_centered := LayPageCenter(LayNumberOfPages - 1);
698    end if;
699    if LayPageCenter(LayNumberOfPages) and not l_prev_centered then
700       htp.p('<CENTER>');
701    elsif not LayPageCenter(LayNumberOfPages) and l_prev_centered then
702       htp.p('</CENTER>');
703    end if;
704 exception
705    when others then
706       raise_application_error(-20000, 'XNP_WSGL.OpenPageBody<br>'||SQLERRM);
707 end;
708 
709 --------------------------------------------------------------------------------
710 -- Name:        ClosePageBody
711 --
712 -- Description: Terminate page with </BODY> and </HTML> tags if appropriate
713 --
714 -- Parameters:  None
715 --
716 --------------------------------------------------------------------------------
717 procedure ClosePageBody is
718   l_this_centered boolean := FALSE;
719 begin
720    if (LayNumberOfPages > 1) then
721       l_this_centered := LayPageCenter(LayNumberOfPages - 1);
722    end if;
723    if l_this_centered and not LayPageCenter(LayNumberOfPages) then
724       htp.p('<CENTER>');
725    elsif not l_this_centered and LayPageCenter(LayNumberOfPages) then
726       htp.p('</CENTER>');
727    end if;
728    if (LayNumberOfPages = 1) then
729       htp.bodyClose;
730       htp.htmlClose;
731    end if;
732    LayNumberOfPages := LayNumberOfPages - 1;
733 exception
734    when others then
735       raise_application_error(-20000, 'XNP_WSGL.ClosePageBody<br>'||SQLERRM);
736 end;
737 
738 --------------------------------------------------------------------------------
739 -- Name:        InBottomFrame
740 --
741 -- Description: Test if building page for bottom frame
742 --
743 -- Parameters:  None
744 --
745 -- Returns:     True if building page for bottom frame
746 --              False otherwise
747 --
748 --------------------------------------------------------------------------------
749 function InBottomFrame return boolean is
750 begin
751    return LayInBottomFrame;
752 end;
753 
754 --------------------------------------------------------------------------------
755 -- Name:        Preformat
756 --
757 -- Description: Builds Preformatted HTML string
758 --
759 -- Parameters:  p_text
760 --
761 -- Returns:     Preformatted HTML string
762 --
763 --------------------------------------------------------------------------------
764 function Preformat(p_text in varchar2) return varchar2 is
765 begin
766    return '<PRE>'||p_text||'</PRE>';
767 end;
768 
769 --------------------------------------------------------------------------------
770 -- Name:        DefaultPageCaption
771 --
772 -- Description:
773 --
774 -- Parameters:  p_caption    IN   Page caption
775 --
776 --------------------------------------------------------------------------------
777 procedure DefaultPageCaption(p_caption in varchar2,
778                              p_headlevel in number) is
779 begin
780    htp.header(nvl(p_headlevel, LayNumberOfPages), p_caption);
781 exception
782    when others then
783       raise_application_error(-20000, 'XNP_WSGL.DefaultPageCaption<br>'||SQLERRM);
784 end;
785 
786 --------------------------------------------------------------------------------
787 -- Name:        BuildWherePredicate
788 --
789 -- Description: The purpose of this procedure is to build WHERE clause
790 --              predicates based on the value of two parameters p_field1
791 --              and p_field2.  The values of these two parameters will be
792 --              determined by values entered into a Query Form.
793 --              If a range query is supported (for numeric and date fields
794 --              which are not in a Primary, Unique or Foreign key constraint)
795 --              then the two parameters are populated independantly from
796 --              two fields on the form, otherwise both parameters are
797 --              populated with the same value, from the same field.
798 --
799 --              Using the value(s) of these two input parameters, the
800 --              Select List Item (SLI) they are constraining, and the
801 --              datatype, a predicate is built and added to the WHERE clause.
802 --
803 --              Values entered for columns of datatype NUMBER or DATE are
804 --              tested to be valid entry by applying to_number/to_date
805 --              functions (using the format mask supplied, if any, for date
806 --              columns).  If this validation fails, an EXCEPTION will be
807 --              raised which should be handled by calling procedure.
808 --
809 --
810 -- Parameters:  p_field1       IN       Query criteria field 1
811 --              p_field2       IN       Query criteria field 2
812 --              p_sli          IN       The Select List Item
813 --              p_datatype     IN       The datatype
814 --              p_where        IN/OUT   The WHERE clause
815 --              p_date_format  IN       (Optional) Date Format Mask
816 --
817 --------------------------------------------------------------------------------
818 function BuildWherePredicate(p_field1   in varchar2,
819                              p_field2   in varchar2,
820                              p_sli      in varchar2,
821                              p_datatype in number,
822                              p_where    in OUT NOCOPY varchar2,
823                              p_date_format in varchar2,
824                              p_caseinsensitive in boolean) return varchar2 is
825    l_predicate varchar2(2000);
826    l_field1    varchar2(255) := rtrim(p_field1);
827    l_field2    varchar2(255) := rtrim(p_field2);
828    l_num1      number;
829    l_num2      number;
830    l_date1     date := null;
831    l_date2     date := null;
832 begin
833    -- check for single apostrophies in query
834    if (instr(l_field1,'''') <> 0) then
835       l_field1:=replace(l_field1,'''','''''');
836    end if;
837    -- No where clause predicate required for this SLI
838    if (l_field1 is null and l_field2 is null) then
839       return null;
840    -- Support user defined expression
841    elsif (substr(ltrim(l_field1), 1, 1) = '#') then
842       l_predicate := p_sli || ' ' || substr(ltrim(l_field1),2);
843    -- Special case where 'Unknown' string is entered for an optional col in a domain
844    elsif (l_field1 = MsgGetText(1,XNP_WSGLM.CAP001_UNKNOWN)) then
845       l_predicate := p_sli || ' is null';
846    -- Add <sli> like '<field1>'
847    elsif (instr(l_field1, '%') <> 0) or (instr(l_field1, '_') <> 0) then
848       if p_datatype = TYPE_DATE then
849          if p_date_format is null then
850             l_predicate := 'to_char('||p_sli||') like ''' || l_field1 || '''';
851          else
852             l_predicate := 'to_char('||p_sli||', '''||p_date_format||
853 
854                            ''') like ''' || l_field1 || '''';
855          end if;
856       elsif p_datatype = TYPE_CHAR_UPPER then
857          l_predicate := p_sli || ' like ''' || upper(l_field1) || '''';
858       elsif p_datatype = TYPE_CHAR and p_caseinsensitive then
859          l_predicate := CaseInsensitivePredicate(p_sli,l_field1,'LIKE');
860       else
861          l_predicate := p_sli || ' like ''' || l_field1 || '''';
862       end if;
863    elsif p_datatype = TYPE_CHAR_UPPER then
864       -- Add <sli> = <field1>
865       l_predicate := p_sli || ' = ''' || upper(l_field1) || '''';
866    elsif p_datatype = TYPE_CHAR and p_caseinsensitive then
867       l_predicate := CaseInsensitivePredicate(p_sli,l_field1,'=');
868    elsif p_datatype = TYPE_CHAR then
869       -- Add <sli> = <field1>
870       l_predicate := p_sli || ' = ''' || l_field1 || '''';
871    elsif p_datatype = TYPE_NUMBER then
872       -- validate the specified field(s) are valid numbers
873       if l_field1 is not null then
874          l_num1 := to_number(l_field1);
875       end if;
876       if l_field2 is not null then
877          l_num2 := to_number(l_field2);
878       end if;
879       -- Add <sli> = <field1>
880       if (l_field1 = l_field2) then
881 
882          l_predicate := p_sli || ' = ' || l_field1;
883       -- Add <sli> <= <field2>
884       elsif (l_field1 is null) then
885          l_predicate := p_sli || ' <= ' || l_field2;
886       -- Add <sli> >= <field1>
887       elsif (l_field2 is null) then
888          l_predicate := p_sli || ' >= ' || l_field1;
889       -- Add <sli> between <field1> and <filed2>
890       elsif (l_num1 < l_num2) then
891          l_predicate := p_sli || ' between ' || l_field1 ||
892                                   ' and ' || l_field2;
893       -- Add <sli> between <field2> and <filed1>
894       else
895          l_predicate := p_sli || ' between ' || l_field2 ||
896                                   ' and ' || l_field1;
897       end if;
898    elsif p_datatype = TYPE_DATE then
899       -- validate the specified field(s) are valid dates
900       if p_date_format is not null and l_field1 is not null then
901          l_date1 := to_date(l_field1, p_date_format);
902       elsif l_field1 is not null then
903       /* ::DPUTHIYE 24/JUN/2005:: Making a quick(n ugly!) fix here to comply to R12 GSCC File.Date.5.
904          GSCC File.Date.5 : to_date should include date format.
905          This file is a Web Server generated file and should not ideally be fixed this way!.
906          But Web Server genrated modules are no longer used in SFM/NP. This should save this fix.
907          Hard-coding date format here. If the date given does not conform, this would throw an exception.
908       */
909          --l_date1 := to_date(l_field1);
910 	 l_date1 := to_date(l_field1, 'MM/DD/YYYY');
911       end if;
912 
913       if p_date_format is not null and l_field2 is not null then
914          l_date2 := to_date(l_field2, p_date_format);
915       elsif l_field2 is not null then
916       /* ::DPUTHIYE 24/JUN/2005:: Making a quick(n ugly!) fix here to comply to R12 GSCC File.Date.5.
917          GSCC File.Date.5 : to_date should include date format.
918          This file is a Web Server generated file and should not ideally be fixed this way!.
919          But Web Server genrated modules are no longer used in SFM/NP. This should save this fix.
920          Hard-coding date format here. If the date given does not conform, this would throw an exception.
921       */
922          --l_date2 := to_date(l_field2);
923          l_date2 := to_date(l_field2, 'MM/DD/YYYY');
924       end if;
925       -- if we get this far, ie no exception raised, then valid dates were entered,
926       -- build strings for RHSs
927       if p_date_format is not null and l_field1 is not null then
928          l_field1 := 'to_date('''||l_field1||''', '''||p_date_format||''')';
929       elsif l_field1 is not null then
930       /* ::DPUTHIYE 24/JUN/2005:: Making a quick(n ugly!) fix here to comply to R12 GSCC File.Date.5.
931          GSCC File.Date.5 : to_date should include date format.
932          This file is a Web Server generated file and should not ideally be fixed this way!.
933          But Web Server genrated modules are no longer used in SFM/NP. This should save this fix.
934          Hard-coding date format here. If the date given does not conform, this would throw an exception.
935       */
936          --l_field1 := 'to_date('''||l_field1||''')';
937          l_field1 := 'to_date('''||l_field1||''', ''MM/DD/YYYY'')';
938       end if;
939       if p_date_format is not null and l_field2 is not null then
940          l_field2 := 'to_date('''||l_field2||''', '''||p_date_format||''')';
941       elsif l_field2 is not null then
942       /* ::DPUTHIYE 24/JUN/2005:: Making a quick(n ugly!) fix here to comply to R12 GSCC File.Date.5.
943          GSCC File.Date.5 : to_date should include date format.
944          This file is a Web Server generated file and should not ideally be fixed this way!.
945          But Web Server genrated modules are no longer used in SFM/NP. This should save this fix.
946          Hard-coding date format here. If the date given does not conform, this would throw an exception.
947       */
948          --l_field2 := 'to_date('''||l_field2||''')';
949          l_field2 := 'to_date('''||l_field2||''', ''MM/DD/YYYY'')';
950       end if;
951       -- Add <sli> = '<field1>'
952       if (l_field1 = l_field2) then
953          l_predicate := p_sli || ' = ' || l_field1;
954       -- Add <sli> <= '<field2>'
955       elsif (l_field1 is null) then
956          l_predicate := p_sli || ' <= ' || l_field2;
957 
958       -- Add <sli> >= '<field1>'
959       elsif (l_field2 is null) then
960          l_predicate := p_sli || ' >= ' || l_field1;
961       -- Add <sli> between '<field1>' and '<field2>'
962       elsif (l_date1 < l_date2) then
963          l_predicate := p_sli || ' between ' || l_field1 || ' and ' || l_field2;
964       -- Add <sli> between '<field1>' and '<field2>'
965       else
966          l_predicate := p_sli || ' between ' || l_field2 || ' and ' || l_field1;
967       end if;
968    end if;
969    return l_predicate;
970 end;
971 
972 --------------------------------------------------------------------------------
973 -- Name:        BuildWhere
974 --
975 -- Description: Overloaded version of buildwhere which is used when there is
976 --              only one Query Criteria filed.  Simply calls the main BuildWhere
977 --              procedure, passing p_field1 in twice.
978 --
979 -- Parameters:  p_field        IN       Query criteria field
980 --              p_sli          IN       The Select List Item
981 --              p_datatype     IN       The datatype
982 --              p_where        IN/OUT   The WHERE clause
983 --              p_date_format  IN       (Optional) Date Format Mask
984 --
985 --------------------------------------------------------------------------------
986 procedure BuildWhere(p_field1   in varchar2,
987                      p_field2   in varchar2,
988                      p_sli      in varchar2,
989                      p_datatype in number,
990                      p_where    in OUT NOCOPY varchar2,
991                      p_date_format in varchar2) is
992    l_predicate varchar2(2000);
993 begin
994    l_predicate := BuildWherePredicate(p_field1, p_field2, p_sli, p_datatype,
995                                       p_where, p_date_format, FALSE);
996    if l_predicate is null then
997       return;
998    elsif p_where is null or p_where = '' then
999       p_where := ' where (' || l_predicate || ')';
1000    else
1001       p_where := p_where || ' and (' || l_predicate || ')';
1002    end if;
1003 end;
1004 
1005 --------------------------------------------------------------------------------
1006 -- Name:        BuildWhere
1007 --
1008 -- Description: Overloaded version of buildwhere which is used when there is
1009 --              only one Query Criteria filed.  Simply calls the main BuildWhere
1010 --              procedure, passing p_field1 in twice.
1011 --
1012 -- Parameters:  p_field        IN       Query criteria field
1013 --              p_sli          IN       The Select List Item
1014 --              p_datatype     IN       The datatype
1015 --              p_where        IN/OUT   The WHERE clause
1016 --              p_date_format  IN       (Optional) Date Format Mask
1017 --
1018 --------------------------------------------------------------------------------
1019 procedure BuildWhere(p_field    in varchar2,
1020                      p_sli      in varchar2,
1021                      p_datatype in number,
1022                      p_where    in OUT NOCOPY varchar2,
1023                      p_date_format in varchar2,
1024                      p_caseinsensitive in boolean) is
1025    l_predicate varchar2(2000);
1026 begin
1027    l_predicate := BuildWherePredicate(p_field, p_field, p_sli, p_datatype,
1028                                       p_where, p_date_format, p_caseinsensitive);
1029    if l_predicate is null then
1030       return;
1031    elsif p_where is null or p_where = '' then
1032       p_where := ' where (' || l_predicate || ')';
1033    else
1034       p_where := p_where || ' and (' || l_predicate || ')';
1035    end if;
1036 end;
1037 
1038 --------------------------------------------------------------------------------
1039 -- Name:        BuildWhere
1040 --
1041 -- Description: Overloaded version of buildwhere which is used when there is
1042 --              only one Query Criteria filed.  Simply calls the main BuildWhere
1043 --              procedure, passing p_field1 in twice.
1044 --
1045 -- Parameters:  p_field        IN       Query criteria field
1046 --              p_sli          IN       The Select List Item
1047 --              p_datatype     IN       The datatype
1048 --              p_where        IN/OUT   The WHERE clause
1049 --              p_date_format  IN       (Optional) Date Format Mask
1050 --
1051 --------------------------------------------------------------------------------
1052 procedure BuildWhere(p_field    in typString240Table,
1053                      p_sli      in varchar2,
1054                      p_datatype in number,
1055                      p_where    in OUT NOCOPY varchar2,
1056                      p_date_format in varchar2) is
1057    l_count number := 1;
1058    l_field varchar2(240);
1059    l_predicate varchar2(2000);
1060    l_new varchar2(2000);
1061 begin
1062    begin
1063       while true loop
1064          l_field := p_field(l_count);
1065          l_predicate := BuildWherePredicate(l_field, l_field, p_sli, p_datatype,
1066                                             p_where, p_date_format, FALSE);
1067          if l_predicate is not null then
1068             if l_new is not null then
1069                l_new := l_new || ' or ';
1070             end if;
1071             l_new := l_new || '(' || l_predicate || ')';
1072          end if;
1073          l_count := l_count + 1;
1074       end loop;
1075    exception
1076       when no_data_found then
1077          null;
1078       when others then
1079          raise;
1080    end;
1081    if l_new is not null then
1082       if p_where is null or p_where = '' then
1083          p_where := ' where (' || l_new || ')';
1084       else
1085          p_where := p_where || ' and (' || l_new || ')';
1086       end if;
1087    end if;
1088 end;
1089 
1090 --------------------------------------------------------------------------------
1091 -- Name:        CaseInsensitivePredicate
1092 --
1093 -- Description: Build an efficient case insensitive query.  This function will
1094 --              build a where clause predicate which attempts to minimise the
1095 --              effect of losing the index on a search column.
1096 --
1097 -- Parameters:  p_sli          IN       The Select List Item
1098 --              p_field        IN       Query criteria field
1099 --              p_operator     IN       The operator (=/like)
1100 --
1101 --------------------------------------------------------------------------------
1102 function CaseInsensitivePredicate(p_sli in varchar2,
1103                                   p_field in varchar2,
1104                                   p_operator in varchar2) return varchar2 is
1105    l_uu  varchar2(100) := null;
1106    l_ul  varchar2(100) := null;
1107    l_lu  varchar2(100) := null;
1108    l_ll  varchar2(100) := null;
1109    l_retval number;
1110 begin
1111    l_retval := SearchComponents(p_field, l_uu, l_ul, l_lu, l_ll);
1112    if l_retval = -1 then
1113       return 'upper('|| p_sli || ') ' || p_operator || ' ''' || upper(p_field) || '''';
1114    elsif l_retval = 0 then
1115       return p_sli || ' ' || p_operator || ' ''' || p_field || '''';
1116    elsif l_retval = 1 then
1117       return p_sli || ' ' || p_operator || ' ''' || l_uu || ''' or ' ||
1118              p_sli || ' ' || p_operator || ' ''' || l_ll || '''';
1119    elsif l_retval = 2 then
1120       return p_sli || ' ' || p_operator || ' ''' || l_uu || ''' or ' ||
1121              p_sli || ' ' || p_operator || ' ''' || l_ul || ''' or ' ||
1122              p_sli || ' ' || p_operator || ' ''' || l_lu || ''' or ' ||
1123              p_sli || ' ' || p_operator || ' ''' || l_ll || '''';
1124    else
1125       return '('|| p_sli || ' like ''' || l_uu || '%'' or ' ||
1126                    p_sli || ' like ''' || l_ul || '%'' or ' ||
1127                    p_sli || ' like ''' || l_lu || '%'' or ' ||
1128                    p_sli || ' like ''' || l_ll || '%'') and upper('||
1129                    p_sli || ') ' || p_operator || ' ''' || upper(p_field) || '''';
1130    end if;
1131 exception
1132    when others then
1133       raise_application_error(-20000, 'XNP_WSGL.CaseInsensitivePredicate<br>'||SQLERRM);
1134       return null;
1135 end;
1136 
1137 --------------------------------------------------------------------------------
1138 -- Name:        SearchComponents
1139 --
1140 -- Description: This procedure determines the components of a case insensitive
1141 --              query.
1142 --
1143 -- Parameters:  p_search  IN      The search string
1144 --              p_uu      IN OUT  Substring with first two alphas uppercase
1145 --              p_ul      IN OUT  Substring with first two alphas upper/lowercase
1146 --              p_lu      IN OUT  Substring with first two alphas lower/uppercase
1147 --              p_ll      IN OUT  Substring with first two alphas lowercase
1148 --
1149 -- Returns:     The number of case sensitive chars in search string
1150 --              -  3 means >2
1151 --              - -1 means the first character was a wild card
1152 --------------------------------------------------------------------------------
1153 function SearchComponents(p_search in varchar2,
1154                           p_uu in OUT NOCOPY varchar2,
1155                           p_ul in OUT NOCOPY varchar2,
1156                           p_lu in OUT NOCOPY varchar2,
1157                           p_ll in OUT NOCOPY varchar2) return number is
1158    l_upp varchar2(4)   := null;
1159    l_low varchar2(4)   := null;
1160    l_chars number      := 0;
1161    l_count number      := 0;
1162 begin
1163 
1164    p_uu := null;
1165    p_ul := null;
1166    p_lu := null;
1167    p_ll := null;
1168 
1169    while ((l_chars < 3) and (l_count < length(p_search))) loop
1170       l_count := l_count + 1;
1171       l_upp := upper(substr(p_search,l_count,1));
1172       l_low := lower(substr(p_search,l_count,1));
1173       if l_upp = l_low then
1174          p_uu := p_uu || l_upp;
1175          p_ul := p_ul || l_upp;
1176          p_lu := p_lu || l_upp;
1177          p_ll := p_ll || l_upp;
1178       else
1179          l_chars := l_chars + 1;
1180          if l_chars = 1 then
1181             p_uu := p_uu || l_upp;
1182             p_ul := p_ul || l_upp;
1183             p_lu := p_lu || l_low;
1184             p_ll := p_ll || l_low;
1185          elsif l_chars = 2 then
1186             p_uu := p_uu || l_upp;
1187             p_ul := p_ul || l_low;
1188             p_lu := p_lu || l_upp;
1189             p_ll := p_ll || l_low;
1190           end if;
1191       end if;
1192    end loop;
1193 
1194    if substr(p_search,1,1) = '%' or substr(p_search,1,1) = '_' then
1195       return -1;
1196    else
1197       return l_chars;
1198    end if;
1199 
1200 exception
1201    when others then
1202       raise_application_error(-20000, 'XNP_WSGL.SearchComponents<br>'||SQLERRM);
1203       return null;
1204 end;
1205 
1206 --------------------------------------------------------------------------------
1207 -- Name:        NavLinks
1208 --
1209 -- Description: Builds 'Menu' of navigation links.
1210 --
1211 -- Parameters:  p_style      IN   The style (LONG/SHORT) or NULL to
1212 --                                indicate end of menu
1213 --              p_caption    IN   The menu/link caption
1214 --              p_menu_level IN   The menu level
1215 --              p_proc       IN   The procedure to call, or null if menu
1216 --                                caption
1217 --
1218 -------------------------------------------------------------------------------
1219 procedure NavLinks(p_style in number,
1220                    p_caption in varchar2,
1221                    p_menu_level in number,
1222                    p_proc in varchar2,
1223                    p_target in varchar2) is
1224    levels number(2) := 0;
1225    i      number(2) := 0;
1226 begin
1227    -- the variable 'levels' is the change in menu level, i.e. indentation,
1228    -- from last level (LayMenuLevel) to the new level (p_menu_level)
1229    if p_style is null then
1230 
1231       -- close all opened menus
1232       levels := LayMenuLevel + 1;
1233       if levels > 0 then
1234          for i in 1..levels loop
1235             htp.menulistClose;
1236          end loop;
1237       end if;
1238       LayMenuLevel := -1;
1239       return;
1240    end if;
1241    if LayMenuLevel = -1 then
1242       -- first menu, put out a line
1243       htp.para;
1244       htp.line;
1245    end if;
1246    -- If there is a change in menu level, open or close menus as
1247    -- appropriate
1248    levels := (p_menu_level - LayMenuLevel);
1249    if levels > 0 then
1250       for i in 1..levels loop
1251          htp.menulistOpen;
1252       end loop;
1253    elsif levels < 0 then
1254 
1255       for i in 1..-levels loop
1256          htp.menulistClose;
1257       end loop;
1258       htp.para;
1259    end if;
1260    -- if a procedure has been defined, build a link to it, or otherwise
1261    -- just display the menu caption
1262    if p_proc is null then
1263       htp.para;
1264       if p_style = MENU_LONG then
1265          htp.listItem;
1266       end if;
1267       htp.bold(p_caption);
1268    elsif p_style = MENU_SHORT then
1269       htp.p(htf.anchor2(p_proc, '['||p_caption||']', ctarget=>p_target)||' ');
1270    elsif p_style = MENU_LONG then
1271       htp.p(htf.listItem||htf.anchor2(p_proc, p_caption, ctarget=>p_target)||' ');
1272    end if;
1273    LayMenuLevel := p_menu_level;
1274 exception
1275    when others then
1276       raise_application_error(-20000, 'XNP_WSGL.NavLinks<br>'||SQLERRM);
1277 end;
1278 
1279 --------------------------------------------------------------------------------
1280 -- Name:        TablesSupported
1281 --
1282 -- Description: Does the current browser support HTML tables?
1283 --
1284 --
1285 -- Parameters:  None
1286 --
1287 -- Returns:     True   If browser supports HTML tables
1288 --              False  Otherwise
1289 --
1290 --------------------------------------------------------------------------------
1291 function TablesSupported return boolean is
1292 begin
1293    -- This function can be modified if it is anticipated that
1294    -- the server/browser combination does not support tables
1295    -- Use owa_util.get_cgi_env('http_user_agent') to get the
1296    -- the name of the browser being used, and construct a test
1297    -- based on that.  Default behaviour is just to return true
1298    -- as all common browsers support HTML tables.
1299    return true;
1300 end;
1301 
1302 --------------------------------------------------------------------------------
1303 -- Name:        EmptyPage
1304 --
1305 -- Description: Create an empty page
1306 --
1307 -- Parameters:  p_attributes IN Body attributes
1308 --
1309 --------------------------------------------------------------------------------
1310 procedure EmptyPage(p_attributes in varchar2) is
1311 begin
1312    DefinePageHead;
1313    OpenPageBody(FALSE, p_attributes);
1314    ClosePageBody;
1315 end;
1316 
1317 --------------------------------------------------------------------------------
1318 -- Name:        EmptyPageURL
1319 --
1320 -- Description: Create URL for call to XNP_WSGL.EmptyPage
1321 --
1322 -- Parameters:  p_attributes IN Body attributes
1323 --
1324 --------------------------------------------------------------------------------
1325 function EmptyPageURL(p_attributes in varchar2 default null) return varchar2 is
1326 begin
1327    return 'XNP_wsgl.emptypage?P_ATTRIBUTES=' ||
1328           replace(replace(replace(p_attributes,' ','%20'),
1329                           '"', '%22'),
1330                   '=', '%3D');
1331 end;
1332 
1333 --------------------------------------------------------------------------------
1334 -- Name:        SubmitButton
1335 --
1336 -- Description: Creates HTML/JavaScript code which is interpreted as follows:
1337 --              - If the Browser does not support JavaScript a Submit button
1338 --                of the given name, and with the given title is created
1339 --              - If the Browser supports JavaScript a button is created with
1340 --                a call to an event handler on the onClick event.  If this is
1341 --                the first call, JavaScript code is also created to build a
1342 --                hidden field called p_name.
1343 --
1344 -- Parameters:  p_name    IN   The name of the submit button, or hidden field
1345 --              p_title   IN   Button caption
1346 --              p_type    IN   The type of button, used in creating name of
1347 --                             event handler
1348 --
1349 --------------------------------------------------------------------------------
1350 procedure SubmitButton(p_name in varchar2,
1351                        p_title in varchar2,
1352                        p_type in varchar2,
1353                        buttonJS in varchar2 default null) is
1354 
1355 New_Button_JS varchar2 (2000) := buttonJS;
1356 
1357 begin
1358    if NOT LayActionCreated then
1359 
1360       htp.p('<SCRIPT><!--');
1361       htp.p('document.write(''<input type=hidden name="'||p_name||'">'')');
1362       htp.p('//-->');
1363       htp.p('</SCRIPT>');
1364       LayActionCreated := true;
1365 
1366    end if;
1367 
1368    htp.p('<SCRIPT><!--');
1369 
1370    if buttonJS is null
1371    then
1372 
1373      htp.p('//--> '||htf.formSubmit(p_name, p_title)||' <!--');
1374      htp.p('document.write(''<input type=button value="'||p_title||'" onClick="' ||p_type||'_OnClick(this)">'')');
1375      htp.p('//-->');
1376      htp.p('</SCRIPT>');
1377 
1378    else
1379 
1380      -- Conditionally escape '' in buttonJS depending upon whether it is already escaped or not
1381 
1382      if instr (buttonJS, '\''', 1) = 0
1383      then
1384 
1385        -- Not already escaped
1386 
1387        New_Button_JS := replace (buttonJS, '''', '\''');
1388 
1389      end if;
1390 
1391      htp.p ('document.write(''<input type=button value="'||p_title||'" onClick="' ||
1392              New_Button_JS || '; ' ||p_type||'_OnClick(this)">'')');
1393      htp.p ('//-->');
1394      htp.p ('</SCRIPT>');
1395 
1396      if XNP_WSGL.IsSupported ('NOSCRIPT')
1397      then
1398 
1399        htp.p ('<NOSCRIPT>');
1400        htp.p (htf.formSubmit(p_name, p_title));
1401        htp.p ('</NOSCRIPT>');
1402 
1403      end if;
1404 
1405    end if;  -- buttonJS is null
1406 
1407 exception
1408    when others then
1409       raise_application_error(-20000, 'XNP_WSGL.SubmitButton<br>'||SQLERRM);
1410 end;
1411 
1412 --------------------------------------------------------------------------------
1413 -- Name:        RecordListButton
1414 --
1415 -- Description: If the functionality of the button is required, an HTML Submit
1416 --              button is created.  If it is not required, for example, the
1417 --              'Next' button, when at the end of the Record List, then either JavaScript
1418 --              code is written out to create a button which issues an Alert with
1419 --              the given message or no buttons are displayed depending on user preference.
1420 --          If JavaScript is not supported, then no button is created.
1421 --
1422 -- Parameters:  p_reqd    IN   Is the button functionality required
1423 --              p_name    IN   Submit Button name
1424 --              p_title   IN   Button caption
1425 --              p_mess    IN   The message to issue if the functionality is not
1426 --                             required
1427 --      p_dojs    IN   Is JS Alert issued or buttons not displayed
1428 --
1429 --------------------------------------------------------------------------------
1430 procedure RecordListButton(p_reqd in boolean,
1431                            p_name in varchar2,
1432                            p_title in varchar2,
1433                            p_mess in varchar2,
1434                   p_dojs in boolean default false,
1435             buttonJS in varchar2 default null
1436                   ) is
1437 
1438 New_Button_JS varchar2 (2000) := buttonJS;
1439 
1440 begin
1441    if (p_reqd) then
1442 
1443      htp.p ('<SCRIPT><!--');
1444 
1445      -- Conditionally escape '' in buttonJS depending upon whether it is already escaped or not
1446 
1447      if instr (buttonJS, '\''', 1) = 0
1448      then
1449 
1450        -- Not already escaped
1451 
1452        New_Button_JS := replace (buttonJS, '''', '\''');
1453 
1454      end if;
1455 
1456      htp.p ('document.write (''<input type=submit value="' || p_title || '" ' || New_Button_JS || '>'')');
1457      htp.p('//-->');
1458      htp.p('</SCRIPT>');
1459 
1460      if XNP_WSGL.IsSupported ('NOSCRIPT')
1461      then
1462 
1463        htp.p ('<NOSCRIPT>');
1464        htp.p (htf.formSubmit(p_name, p_title));
1465        htp.p ('</NOSCRIPT>');
1466 
1467      end if;
1468 
1469    elsif (p_dojs) then
1470 
1471      LayNumberOfRLButs := LayNumberOfRLButs + 1;
1472      htp.p('<SCRIPT><!--');
1473      htp.p('var msg'||to_char(LayNumberOfRLButs)||'="'||p_mess||'"');
1474      htp.p('document.write(''<input type=button value="'||p_title||
1475            '" onClick="alert(msg'||to_char(LayNumberOfRLButs)||')">'')');
1476      htp.p('//-->');
1477      htp.p('</SCRIPT>');
1478 
1479      if XNP_WSGL.IsSupported ('NOSCRIPT')
1480      then
1481 
1482        htp.p ('<NOSCRIPT>');
1483        htp.p (htf.formSubmit(p_name, p_title));
1484        htp.p ('</NOSCRIPT>');
1485 
1486      end if;
1487 
1488    end if;
1489 exception
1490    when others then
1491       raise_application_error(-20000, 'XNP_WSGL.RecordListButton<br>'||SQLERRM);
1492 end;
1493 
1494 --------------------------------------------------------------------------------
1495 -- Name:        CountHits
1496 --
1497 -- Description: Takes a SQL SELECT statement and replaces the Select list
1498 --              with count(*), then executes the SQL to return the number
1499 --              of hits.
1500 --
1501 -- Parameters:  P_SQL  The SELECT statement
1502 --
1503 -- Returns:     Number of hits
1504 --              -1 if an error occurs
1505 --
1506 --------------------------------------------------------------------------------
1507    function  CountHits(
1508              P_SQL in varchar2) return number is
1509       I_QUERY     varchar2(2000) := '';
1510       I_CURSOR    integer;
1511       I_VOID      integer;
1512       I_FROM_POS  integer := 0;
1513       I_COUNT     number(10);
1514    begin
1515       I_FROM_POS := instr(upper(P_SQL), ' FROM ');
1516       if I_FROM_POS = 0 then
1517          return -1;
1518       end if;
1519       I_QUERY := 'SELECT count(*)' ||
1520                  substr(P_SQL, I_FROM_POS);
1521       I_CURSOR := dbms_sql.open_cursor;
1522       dbms_sql.parse(I_CURSOR, I_QUERY, dbms_sql.v7);
1523       dbms_sql.define_column(I_CURSOR, 1, I_COUNT);
1524       I_VOID := dbms_sql.execute(I_CURSOR);
1525       I_VOID := dbms_sql.fetch_rows(I_CURSOR);
1526 
1527       dbms_sql.column_value(I_CURSOR, 1, I_COUNT);
1528       dbms_sql.close_cursor(I_CURSOR);
1529       return I_COUNT;
1530    exception
1531       when others then
1532          return -1;
1533    end;
1534 
1535 --------------------------------------------------------------------------------
1536 -- Name:        LoadDomainValues
1537 --
1538 -- Description: Load values into Domain Record from the specified Ref Codes
1539 --              Table
1540 --
1541 -- Parameters:  P_REF_CODE_TABLE The name of the Ref Codes Table
1542 --              P_DOMAIN         The name of the domain
1543 --              P_DVREC          Record defining Domain details to be loaded
1544 --
1545 --------------------------------------------------------------------------------
1546    procedure LoadDomainValues(
1547              P_REF_CODE_TABLE in varchar2,
1548              P_DOMAIN in varchar2,
1549              P_DVREC in OUT NOCOPY typDVRecord) is
1550       I_CURSOR      integer;
1551 
1552       I_VOID        integer;
1553       I_ROWS        integer := 0;
1554       I_SQL         varchar2(256);
1555       L_VALUE       varchar2(240);
1556       L_MEANING     varchar2(240);
1557       L_ABBR        varchar2(240);
1558    begin
1559 
1560       -- Using Apps style lookups with FND_LOOKUPS now.
1561       --
1562       -- I_SQL := 'SELECT RV_LOW_VALUE, RV_MEANING, RV_ABBREVIATION
1563       --         FROM   ' || P_REF_CODE_TABLE ||
1564       --     ' WHERE  RV_DOMAIN = ''' || P_DOMAIN ||
1565       --   ''' ORDER BY ';
1566 
1567 
1568       I_SQL := 'SELECT LOOKUP_CODE, MEANING, LOOKUP_CODE ABBR
1569       		FROM FND_LOOKUPS
1570       		WHERE  LOOKUP_TYPE = ''' || P_DOMAIN ||
1571       		''' ORDER BY ';
1572 
1573       if P_DVREC.UseMeanings then
1574          I_SQL := I_SQL || 'MEANING';
1575       else
1576          I_SQL := I_SQL || 'LOOKUP_CODE';
1577       end if;
1578       I_CURSOR := dbms_sql.open_cursor;
1579       dbms_sql.parse(I_CURSOR, I_SQL, dbms_sql.v7);
1580       dbms_sql.define_column(I_CURSOR, 1, L_VALUE, 240);
1581       dbms_sql.define_column(I_CURSOR, 2, L_MEANING, 240);
1582       dbms_sql.define_column(I_CURSOR, 3, L_ABBR, 240);
1583       I_VOID := dbms_sql.execute(I_CURSOR);
1584       while (dbms_sql.fetch_rows(I_CURSOR) <> 0) loop
1585 
1586          I_ROWS := I_ROWS + 1;
1587          dbms_sql.column_value(I_CURSOR, 1, L_VALUE);
1588          dbms_sql.column_value(I_CURSOR, 2, L_MEANING);
1589          dbms_sql.column_value(I_CURSOR, 3, L_ABBR);
1590          P_DVREC.Vals(I_ROWS) := L_VALUE;
1591          P_DVREC.Meanings(I_ROWS) := L_MEANING;
1592          P_DVREC.Abbreviations(I_ROWS) := L_ABBR;
1593       end loop;
1594       P_DVREC.NumOfVV := I_ROWS;
1595       dbms_sql.close_cursor(I_CURSOR);
1596    exception
1597       when others then
1598          raise_application_error(-20000, 'XNP_WSGL.LoadDomainValues<br>'||SQLERRM);
1599    end;
1600 
1601 --------------------------------------------------------------------------------
1602 -- Name:        ValidDomainValue
1603 --
1604 -- Description: Tests whether the given value is valid for the specified domain
1605 --
1606 -- Parameters:  P_DVREC      Record defining Domain details
1607 --              P_VALUE      The value to test
1608 --                           - If an abbreviation or meaning was entered,
1609 --                             this is replaced by the value
1610 --
1611 -- Returns:     True if valid value
1612 --              False otherwise
1613 --
1614 --------------------------------------------------------------------------------
1615    function ValidDomainValue(
1616             P_DVREC in typDVRecord,
1617             P_VALUE in OUT NOCOPY varchar2) return boolean is
1618       I_LOOP integer;
1619    begin
1620       if not P_DVREC.Initialised then
1621          raise_application_error(-20000, 'XNP_WSGL.ValidDomainValue<br>'||MsgGetText(201,XNP_WSGLM.MSG201_DV_INIT_ERR));
1622       end if;
1623 --      if P_VALUE is null and P_DVREC.ColOptional then
1624       if P_VALUE is null then
1625          return true;
1626       end if;
1627 
1628       for I_LOOP in 1..P_DVREC.NumOfVV loop
1629           if (P_VALUE = P_DVREC.Vals(I_LOOP))
1630           then
1631               return true;
1632           end if;
1633       end loop;
1634 
1635       if (P_DVREC.UseMeanings)
1636       then
1637           for I_LOOP in 1..P_DVREC.NumOfVV loop
1638               if (P_VALUE = P_DVREC.Meanings(I_LOOP))
1639               then
1640                   P_VALUE := P_DVREC.Vals(I_LOOP);
1641                   return true;
1642               end if;
1643           end loop;
1644       end if;
1645 
1646       for I_LOOP in 1..P_DVREC.NumOfVV loop
1647          if (P_VALUE = P_DVREC.Abbreviations(I_LOOP))
1648          then
1649              P_VALUE := P_DVREC.Vals(I_LOOP);
1650              return true;
1651          end if;
1652       end loop;
1653 
1654       return false;
1655    exception
1656       when others then
1657          raise_application_error(-20000, 'XNP_WSGL.ValidDomainValue<br>'||SQLERRM);
1658    end;
1659 
1660 --------------------------------------------------------------------------------
1661 -- Name:        DomainMeaning
1662 --
1663 -- Description: Returns the meaning of a value in a domain
1664 --
1665 -- Parameters:  P_DVREC      Record defining Domain details
1666 --              P_VALUE      The value
1667 --
1668 -- Returns:     The associated meaning of the domain value if found
1669 --              The value, otherwise
1670 --
1671 --------------------------------------------------------------------------------
1672    function DomainMeaning(
1673             P_DVREC in typDVRecord,
1674 
1675             P_VALUE in varchar2) return varchar2 is
1676       I_LOOP integer;
1677    begin
1678       if not P_DVREC.Initialised then
1679          raise_application_error(-20000, 'XNP_WSGL.DomainMeaning<br>'||MsgGetText(201,XNP_WSGLM.MSG201_DV_INIT_ERR));
1680       end if;
1681       if P_DVREC.UseMeanings then
1682          for I_LOOP in 1..P_DVREC.NumOfVV loop
1683             if P_VALUE = P_DVREC.Vals(I_LOOP) then
1684                return P_DVREC.Meanings(I_LOOP);
1685             end if;
1686          end loop;
1687       end if;
1688       return P_VALUE;
1689    exception
1690       when others then
1691          raise_application_error(-20000, 'XNP_WSGL.DomainMeaning<br>'||SQLERRM);
1692    end;
1693 
1694 --------------------------------------------------------------------------------
1695 -- Name:        DomainValue
1696 --
1697 -- Description: Returns the value of a domain whose meaning is given
1698 --
1699 -- Parameters:  P_DVREC      Record defining Domain details
1700 --              P_MEANING    The meaning
1701 --
1702 -- Returns:     The associated value of the domain if found
1703 --              The meaning, otherwise
1704 --
1705 --------------------------------------------------------------------------------
1706    function DomainValue(
1707             P_DVREC in typDVRecord,
1708             P_MEANING in varchar2) return varchar2 is
1709       I_LOOP integer;
1710    begin
1711       if not P_DVREC.Initialised then
1712          raise_application_error(-20000, 'XNP_WSGL.DomainValue<br>'||MsgGetText(201,XNP_WSGLM.MSG201_DV_INIT_ERR));
1713       end if;
1714       if P_DVREC.UseMeanings then
1715          for I_LOOP in 1..P_DVREC.NumOfVV loop
1716             if P_MEANING = P_DVREC.Meanings(I_LOOP) then
1717                return P_DVREC.Vals(I_LOOP);
1718             end if;
1719          end loop;
1720       end if;
1721       return P_MEANING;
1722    exception
1723       when others then
1724          raise_application_error(-20000, 'XNP_WSGL.DomainValue<br>'||SQLERRM);
1725    end;
1726 
1727 
1728 --------------------------------------------------------------------------------
1729 -- Name:        DomainValue
1730 --
1731 -- Description: Returns the value of a domain whose meaning is given
1732 --
1733 -- Parameters:  P_DVREC      Record defining Domain details
1734 --              P_MEANING    The meaning
1735 --
1736 -- Returns:     The associated value of the domain if found
1737 --              The meaning, otherwise
1738 --
1739 --------------------------------------------------------------------------------
1740 function DomainValue(
1741          P_DVREC in typDVRecord,
1742          P_MEANING in typString240Table) return typString240Table is
1743    ret_array typString240Table;
1744    i number := 1;
1745 begin
1746    while true loop
1747       ret_array(i) := DomainValue(P_DVREC, P_MEANING(i));
1748       i := i+1;
1749    end loop;
1750 exception
1751    when no_data_found then
1752       return ret_array;
1753    when others then
1754       raise_application_error(-20000, 'XNP_WSGL.DomainValue2<br>'||SQLERRM);
1755 end;
1756 
1757 --------------------------------------------------------------------------------
1758 -- Name:        BuildDVControl
1759 --
1760 -- Description: Builds the HTML required to render the given domain
1761 --
1762 -- Parameters:  P_DVREC      Record defining Domain details
1763 --              P_CTL_STYLE  CTL_READONLY - Read only
1764 --                           CTL_UPDATABLE - Updatable
1765 --                           CTL_INSERTABLE - Insertable
1766 --                           CTL_QUERY - Query
1767 --              P_CURR_VAL   The current value of the column
1768 --
1769 -- Returns:     The HTML required to render the given domain
1770 --
1771 --------------------------------------------------------------------------------
1772    function BuildDVControl(
1773             P_DVREC in typDVRecord,
1774             P_CTL_STYLE in number,
1775             P_CURR_VAL in varchar2,
1776             p_onclick in boolean default false,
1777 
1778             p_onchange in boolean default false,
1779             p_onblur in boolean default false,
1780             p_onfocus in boolean default false,
1781             p_onselect in boolean default false) return varchar2 is
1782       L_RET_VALUE varchar2(20000) := null;
1783       L_DISPLAY_VAL varchar2(200);
1784       l_events varchar2(1000) := null;
1785    begin
1786       if (P_CTL_STYLE = CTL_UPDATABLE or P_CTL_STYLE = CTL_INSERTABLE) then
1787          if p_onclick then
1788             l_events := l_events || ' onClick="'||P_DVREC.ColAlias||'_OnClick(this)"';
1789          end if;
1790          if p_onchange then
1791             l_events := l_events || ' onChange="'||P_DVREC.ColAlias||'_OnChange(this)"';
1792          end if;
1793          if p_onblur then
1794             l_events := l_events || ' onBlur="'||P_DVREC.ColAlias||'_OnBlur(this)"';
1795          end if;
1796          if p_onfocus then
1797             l_events := l_events || ' onFocus="'||P_DVREC.ColAlias||'_OnFocus(this)"';
1798          end if;
1799          if p_onselect then
1800             l_events := l_events || ' onSelect="'||P_DVREC.ColAlias||'_OnSelect(this)"';
1801          end if;
1802       end if;
1803       if not P_DVREC.Initialised then
1804          raise_application_error(-20000, 'XNP_WSGL.BuildDVControl<br>'||MsgGetText(201,XNP_WSGLM.MSG201_DV_INIT_ERR));
1805       end if;
1806       if P_DVREC.UseMeanings then
1807          L_DISPLAY_VAL := DomainMeaning(P_DVREC, P_CURR_VAL);
1808       else
1809          L_DISPLAY_VAL := P_CURR_VAL;
1810       end if;
1811       if P_CTL_STYLE = CTL_READONLY then
1812          return L_DISPLAY_VAL;
1813       end if;
1814       if P_DVREC.ControlType = DV_TEXT then
1815          if (P_CTL_STYLE = CTL_UPDATABLE or P_CTL_STYLE = CTL_INSERTABLE) then
1816             L_RET_VALUE := htf.formText('P_'||P_DVREC.ColAlias,
1817                                          to_char(P_DVREC.DispWidth),
1818                                          to_char(P_DVREC.MaxWidth),
1819                                          replace(L_DISPLAY_VAL,'"','"'),
1820                                          cattributes=>l_events);
1821          else
1822             L_RET_VALUE := htf.formText('P_'||P_DVREC.ColAlias,
1823                                          to_char(P_DVREC.DispWidth));
1824          end if;
1825      elsif P_DVREC.ControlType = DV_LIST then
1826 
1827          if P_CTL_STYLE = CTL_QUERY and (P_DVREC.DispHeight <> 1) then
1828             L_RET_VALUE := htf.formSelectOpen('P_'||P_DVREC.ColAlias,
1829                                               nsize=>to_char(P_DVREC.DispHeight),
1830                                               cattributes=>'MULTIPLE '||l_events);
1831          else
1832             L_RET_VALUE := htf.formSelectOpen('P_'||P_DVREC.ColAlias,
1833                                               nsize=>to_char(P_DVREC.DispHeight),
1834                                               cattributes=>l_events);
1835          end if;
1836          if (P_CTL_STYLE = CTL_UPDATABLE or P_CTL_STYLE = CTL_INSERTABLE) and P_DVREC.ColOptional then
1837             L_RET_VALUE := L_RET_VALUE || htf.formSelectOption(' ');
1838          end if;
1839          if P_CTL_STYLE = CTL_QUERY then
1840             L_RET_VALUE := L_RET_VALUE || htf.formSelectOption(' ', 'SELECTED');
1841          end if;
1842          for I_LOOP in 1..P_DVREC.NumOfVV loop
1843             if P_DVREC.UseMeanings then
1844                L_DISPLAY_VAL := P_DVREC.Meanings(I_LOOP);
1845             else
1846                L_DISPLAY_VAL := P_DVREC.Vals(I_LOOP);
1847             end if;
1848             if P_DVREC.Vals(I_LOOP) = DomainValue(P_DVREC, P_CURR_VAL) then
1849                L_RET_VALUE := L_RET_VALUE || htf.formSelectOption(L_DISPLAY_VAL, 'SELECTED',
1850                                              'VALUE="'||P_DVREC.Vals(I_LOOP)||'"');
1851             else
1852                L_RET_VALUE := L_RET_VALUE || htf.formSelectOption(L_DISPLAY_VAL, NULL,
1853                                              'VALUE="'||P_DVREC.Vals(I_LOOP)||'"');
1854             end if;
1855          end loop;
1856          if P_CTL_STYLE = CTL_QUERY and P_DVREC.ColOptional then
1857             L_RET_VALUE := L_RET_VALUE || htf.formSelectOption(MsgGetText(1,XNP_WSGLM.CAP001_UNKNOWN));
1858          end if;
1859          L_RET_VALUE := L_RET_VALUE || htf.formSelectClose;
1860      elsif (P_DVREC.ControlType = DV_CHECK) and (P_CTL_STYLE <> CTL_QUERY) then
1861         if P_CURR_VAL = P_DVREC.Vals(1) then
1862            L_RET_VALUE := htf.formCheckbox('P_'||P_DVREC.ColAlias, P_DVREC.Vals(1), 'CHECKED', cattributes=>l_events);
1863         else
1864            L_RET_VALUE := htf.formCheckbox('P_'||P_DVREC.ColAlias, P_DVREC.Vals(1), cattributes=>l_events);
1865         end if;
1866      elsif ((P_DVREC.ControlType = DV_RADIO) or
1867             ((P_DVREC.ControlType = DV_CHECK) and (P_CTL_STYLE = CTL_QUERY))
1868            ) then
1869          for I_LOOP in 1..P_DVREC.NumOfVV loop
1870             if P_DVREC.UseMeanings or P_DVREC.Vals(I_LOOP) is null then
1871                L_DISPLAY_VAL := P_DVREC.Meanings(I_LOOP);
1872             else
1873                L_DISPLAY_VAL := P_DVREC.Vals(I_LOOP);
1874             end if;
1875             if ((P_DVREC.Vals(I_LOOP) = DomainValue(P_DVREC, P_CURR_VAL)) or
1876                 ( (not P_DVREC.ColOptional) and (P_CURR_VAL is null) and
1877                   (P_CTL_STYLE = CTL_INSERTABLE) and (I_LOOP = 1))
1878                ) then
1879                L_RET_VALUE := L_RET_VALUE ||
1880                                htf.formRadio('P_'||P_DVREC.ColAlias,
1881                                              P_DVREC.Vals(I_LOOP),
1882                                              'CHECKED',
1883                                               cattributes=>l_events);
1884             else
1885                L_RET_VALUE := L_RET_VALUE ||
1886                                htf.formRadio('P_'||P_DVREC.ColAlias,
1887                                              P_DVREC.Vals(I_LOOP),
1888                                              cattributes=>l_events);
1889             end if;
1890             L_RET_VALUE := L_RET_VALUE || ' ' || L_DISPLAY_VAL;
1891             if I_LOOP <> P_DVREC.NumOfVV then
1892                if LayStyle = LAYOUT_TABLE then
1893                   L_RET_VALUE := L_RET_VALUE || htf.nl;
1894                else
1895                   L_RET_VALUE := L_RET_VALUE || ' ';
1896                end if;
1897             end if;
1898          end loop;
1899 
1900          if P_DVREC.ColOptional then
1901             if LayStyle = LAYOUT_TABLE then
1902                L_RET_VALUE := L_RET_VALUE || htf.nl;
1903             else
1904                L_RET_VALUE := L_RET_VALUE || ' ';
1905             end if;
1906             if P_CURR_VAL is null and (P_CTL_STYLE = CTL_UPDATABLE or P_CTL_STYLE = CTL_INSERTABLE) then
1907                L_RET_VALUE := L_RET_VALUE ||
1908                                htf.formRadio('P_'||P_DVREC.ColAlias,
1909                                              null,
1910                                              'CHECKED',
1911                                              cattributes=>l_events);
1912             elsif (P_CTL_STYLE = CTL_UPDATABLE or P_CTL_STYLE = CTL_INSERTABLE) then
1913                L_RET_VALUE := L_RET_VALUE ||
1914                                htf.formRadio('P_'||P_DVREC.ColAlias,
1915                                              null,
1916                                              cattributes=>l_events);
1917             else
1918                L_RET_VALUE := L_RET_VALUE ||
1919                                htf.formRadio('P_'||P_DVREC.ColAlias,
1920                                              MsgGetText(1,XNP_WSGLM.CAP001_UNKNOWN),
1921                                              cattributes=>l_events);
1922             end if;
1923             L_RET_VALUE := L_RET_VALUE || ' ' || MsgGetText(1,XNP_WSGLM.CAP001_UNKNOWN);
1924 
1925          end if;
1926       else
1927          raise_application_error(-20000, 'XNP_WSGL.BuildDVControl<br>'||MsgGetText(202,XNP_WSGLM.MSG202_DV_CTL_ERR));
1928          return '';
1929       end if;
1930       return L_RET_VALUE;
1931    exception
1932       when others then
1933          raise_application_error(-20000, 'XNP_WSGL.BuildDVControl<br>'||SQLERRM);
1934    end;
1935 
1936 --------------------------------------------------------------------------------
1937 -- Name:        BuildTextControl
1938 --
1939 -- Description: Create a text control
1940 --
1941 -- Parameters:  p_alias     IN The alias of the control
1942 --              p_size      IN The display width
1943 --              p_height    IN The height (if > 1, then text area)
1944 --              p_maxlength IN The maximum length of data
1945 --              p_value     IN Current value
1946 --              p_onclick   IN Is an OnClick event required
1947 --              p_onchange  IN Is an OnChange event required
1948 --              p_onblur    IN Is an OnBlur event required
1949 --              p_onfocus   IN Is an OnFocus event required
1950 --              p_onselect  IN Is an OnSelect event required
1951 --
1952 --------------------------------------------------------------------------------
1953 function BuildTextControl(p_alias in varchar2,
1954                           p_size in varchar2 default null,
1955                           p_height in varchar2 default null,
1956                           p_maxlength in varchar2 default null,
1957                           p_value in varchar2 default null,
1958                           p_onclick in boolean default false,
1959                           p_onchange in boolean default false,
1960                           p_onblur in boolean default false,
1961                           p_onfocus in boolean default false,
1962                           p_onselect in boolean default false) return varchar2 is
1963    l_name   varchar2(30) := 'P_'||p_alias;
1964    l_events varchar2(1000) := null;
1965    l_rows  integer := to_number(p_height);
1966    l_cols  integer := to_number(p_size);
1967 begin
1968    if p_onclick then
1969       l_events := l_events || ' onClick="'||p_alias||'_OnClick(this)"';
1970    end if;
1971    if p_onchange then
1972       l_events := l_events || ' onChange="'||p_alias||'_OnChange(this)"';
1973    end if;
1974    if p_onblur then
1975       l_events := l_events || ' onBlur="'||p_alias||'_OnBlur(this)"';
1976    end if;
1977    if p_onfocus then
1978       l_events := l_events || ' onFocus="'||p_alias||'_OnFocus(this)"';
1979    end if;
1980    if p_onselect then
1981       l_events := l_events || ' onSelect="'||p_alias||'_OnSelect(this)"';
1982    end if;
1983    if p_height = '1' then
1984       return htf.formText(cname=>l_name, csize=>p_size, cmaxlength=>p_maxlength,
1985                           cvalue=>replace(p_value,'"','"'), cattributes=>l_events);
1986    else
1987       return htf.formTextareaOpen2(cname=>l_name, nrows=>l_rows, ncolumns=>l_cols, cwrap=>'VIRTUAL', cattributes=>l_events) ||
1988              replace(p_value,'"','"') ||
1989              htf.formTextareaClose;
1990    end if;
1991 exception
1992    when others then
1993       raise_application_error(-20000, 'XNP_WSGL.BuildTextControl<br>'||SQLERRM);
1994 end;
1995 
1996 --------------------------------------------------------------------------------
1997 -- Name:        BuildQueryControl
1998 --
1999 -- Description: Create text control(s) for query form
2000 --
2001 -- Parameters:  p_alias     IN The alias of the control
2002 --              p_size      IN The display width
2003 --              p_onclick   IN Is an OnClick event required
2004 --              p_onchange  IN Is an OnChange event required
2005 --              p_onblur    IN Is an OnBlur event required
2006 --              p_onfocus   IN Is an OnFocus event required
2007 --              p_onselect  IN Is an OnSelect event required
2008 --
2009 --------------------------------------------------------------------------------
2010 function BuildQueryControl(
2011          p_alias in varchar2,
2012          p_size in varchar2,
2013          p_range in boolean,
2014          p_onclick in boolean,
2015          p_onchange in boolean,
2016          p_onblur in boolean,
2017          p_onfocus in boolean,
2018          p_onselect in boolean) return varchar2 is
2019    l_name1   varchar2(30) := 'P_'||p_alias;
2020    l_name2   varchar2(30) := 'U_'||p_alias;
2021    l_events  varchar2(1000) := null;
2022 begin
2023    if p_onclick then
2024       l_events := l_events || ' onClick="'||p_alias||'_OnClick(this)"';
2025    end if;
2026    if p_onchange then
2027       l_events := l_events || ' onChange="'||p_alias||'_OnChange(this)"';
2028    end if;
2029    if p_onblur then
2030       l_events := l_events || ' onBlur="'||p_alias||'_OnBlur(this)"';
2031    end if;
2032    if p_onfocus then
2033       l_events := l_events || ' onFocus="'||p_alias||'_OnFocus(this)"';
2034    end if;
2035    if p_onselect then
2036       l_events := l_events || ' onSelect="'||p_alias||'_OnSelect(this)"';
2037    end if;
2038    if not p_range then
2039       return htf.formText(cname=>l_name1, csize=>p_size, cattributes=>l_events);
2040    else
2041       return htf.formText(cname=>l_name1, csize=>p_size, cattributes=>l_events) || ' ' ||
2042              htf.bold(MsgGetText(119,XNP_WSGLM.DSP119_RANGE_TO)) || ' ' ||
2043              htf.formText(cname=>l_name2, csize=>p_size, cattributes=>l_events);
2044    end if;
2045 exception
2046    when others then
2047       raise_application_error(-20000, 'XNP_WSGL.BuildQueryControl<br>'||SQLERRM);
2048 end;
2049 
2050 --------------------------------------------------------------------------------
2051 -- Name:        BuildDerivationControl
2052 --
2053 -- Description: Create a text control for displaying a derivation expression if
2054 --              JavaScript is supported, otherwise, just display the value
2055 --
2056 -- Parameters:  p_name      IN The name of the control
2057 --              p_size      IN The display width
2058 --              p_value     IN Current value
2059 --
2060 --------------------------------------------------------------------------------
2061 function BuildDerivationControl(p_name in varchar2,
2062                                 p_size in varchar2,
2063                                 p_value in varchar2,
2064                                 p_onclick in boolean,
2065                                 p_onblur in boolean,
2066                                 p_onfocus in boolean,
2067                                 p_onselect in boolean) return varchar2 is
2068    l_events  varchar2(1000) := 'onChange="'||substr(p_name, 3)||'_OnChange(this)"';
2069 begin
2070    if p_onclick then
2071       l_events := l_events || ' onClick="'||substr(p_name, 3)||'_OnClick(this)"';
2072    end if;
2073    if p_onblur then
2074       l_events := l_events || ' onBlur="'||substr(p_name, 3)||'_OnBlur(this)"';
2075    end if;
2076    if p_onfocus then
2077       l_events := l_events || ' onFocus="'||substr(p_name, 3)||'_OnFocus(this)"';
2078    end if;
2079    if p_onselect then
2080       l_events := l_events || ' onSelect="'||substr(p_name, 3)||'_OnSelect(this)"';
2081    end if;
2082    return '
2083 <SCRIPT><!--
2084 //--> '||p_value||' <!--
2085 document.write(''<input type=text name="'||p_name||'" value="'||p_value||'" size="'||p_size||'" '||l_events||'>'')
2086 //-->
2087 </SCRIPT>
2088 ';
2089 exception
2090    when others then
2091       raise_application_error(-20000, 'XNP_WSGL.BuildDerivationControl<br>'||SQLERRM);
2092 end;
2093 
2094 --------------------------------------------------------------------------------
2095 -- Name:        HiddenField
2096 --
2097 -- Description: Create a hidden field with given value
2098 --
2099 --------------------------------------------------------------------------------
2100 procedure HiddenField(p_paramname in varchar2,
2101                       p_paramval in varchar2) is
2102 begin
2103    htp.formHidden(p_paramname, replace(p_paramval,'"','"'));
2104 exception
2105    when others then
2106       raise_application_error(-20000, 'XNP_WSGL.HiddenField<br>'||SQLERRM);
2107 end;
2108 
2109 --------------------------------------------------------------------------------
2110 -- Name:        HiddenField
2111 --
2112 -- Description: Create hidden fields with given values
2113 --
2114 --------------------------------------------------------------------------------
2115 procedure HiddenField(p_paramname in varchar2,
2116                       p_paramval in typString240Table) is
2117    i number := 1;
2118 begin
2119    while true loop
2120       htp.formHidden(p_paramname, replace(p_paramval(i),'"','"'));
2121       i := i+1;
2122    end loop;
2123 exception
2124    when no_data_found then
2125       null;
2126    when others then
2127       raise_application_error(-20000, 'XNP_WSGL.HiddenField2<br>'||SQLERRM);
2128 end;
2129 
2130 --------------------------------------------------------------------------------
2131 -- Name:        DisplayMessage
2132 --
2133 -- Description: Provides mechanism for display of messages
2134 --
2135 -- Parameters:  p_mess    The info message
2136 --
2137 --------------------------------------------------------------------------------
2138 procedure DisplayMessage(p_type in number,
2139                          p_mess in varchar2,
2140                          p_title in varchar2,
2141                          p_attributes in varchar2,
2142                          p_location in varchar2,
2143                          p_context in varchar2,
2144                          p_action in varchar2) is
2145    l_mess varchar2(2000) := htf.bold(htf.header(2,p_mess));
2146 begin
2147    -- Build HTML output string
2148    l_mess := replace(p_mess, '
2149 ', '<br>
2150 ');
2151    DefinePageHead(p_title);
2152    OpenPageBody(FALSE, p_attributes);
2153    if LayNumberOfPages = 1 then
2154       DefaultPageCaption(p_title);
2155       htp.para;
2156    end if;
2157    if p_type = MESS_INFORMATION then
2158       htp.bold(l_mess);
2159    elsif p_type = MESS_SUCCESS then
2160       htp.bold('<font color="008000" size=+2>'||htf.italic(MsgGetText(121,XNP_WSGLM.DSP121_SUCCESS))||
2161                 '</font><br>'||l_mess);
2162    elsif p_type = MESS_WARNING then
2163       -- NB, MESS_WARNING not used at present, just issue error message
2164       htp.bold('<font color="ff4040" size=+2>'||htf.italic(MsgGetText(122,XNP_WSGLM.DSP122_ERROR))||
2165                 '</font><br>'||l_mess);
2166    elsif p_type = MESS_ERROR then
2167 
2168       htp.bold('<font color="ff4040" size=+2>'||htf.italic(MsgGetText(122,XNP_WSGLM.DSP122_ERROR))||
2169                 '</font><br>'||l_mess);
2170    elsif p_type = MESS_ERROR_QRY then
2171       htp.bold('<font color="ff4040" size=+2>'||htf.italic(MsgGetText(122,XNP_WSGLM.DSP122_ERROR))||
2172                '</font><br>');
2173       htp.bold(p_context);
2174       htp.para;
2175       htp.small(l_mess);
2176       if p_action is not null then
2177          htp.para;
2178          htp.bold(p_action);
2179       end if;
2180    elsif p_type = MESS_EXCEPTION then
2181       htp.bold('<font color="ff4040" size=+2>'||htf.italic(MsgGetText(122,XNP_WSGLM.DSP122_ERROR))||
2182                '</font><br>');
2183       htp.bold(MsgGetText(217,XNP_WSGLM.MSG217_EXCEPTION, p_location));
2184       htp.para;
2185       htp.p(l_mess);
2186       htp.para;
2187       htp.bold(MsgGetText(218,XNP_WSGLM.MSG218_CONTACT_SUPPORT));
2188    end if;
2189    htp.para;
2190    ClosePageBody;
2191 end;
2192 
2193 --------------------------------------------------------------------------------
2194 -- Name:        StoreErrorMessage
2195 --
2196 -- Description: Pushes error message onto CG$ERRORS error stack
2197 --
2198 -- Parameters:  p_mess   The message
2199 --
2200 --------------------------------------------------------------------------------
2201 procedure StoreErrorMessage(p_mess in varchar2) is
2202 begin
2203   XNP_cg$errors.push(p_mess,'E','WSG',0,null);
2204 end;
2205 
2206 
2207 --------------------------------------------------------------------------------
2208 -- Name:        MsgGetText
2209 --
2210 -- Description: Provides a mechanism for text translation.
2211 --
2212 -- Parameters:  p_MsgNo    The Id of the message
2213 --              p_DfltText The Default Text
2214 --              p_Subst1 (to 3) Substitution strings
2215 --              p_LangId   The Language ID
2216 --
2217 --------------------------------------------------------------------------------
2218 function MsgGetText(p_MsgNo in number,
2219                     p_DfltText in varchar2,
2220                     p_Subst1 in varchar2,
2221                     p_Subst2 in varchar2,
2222                     p_Subst3 in varchar2,
2223                     p_LangId in number) return varchar2 is
2224    l_temp varchar2(10000) := p_DfltText;
2225 begin
2226    l_temp := replace(l_temp, '<p>',  p_Subst1);
2227    l_temp := replace(l_temp, '<p1>', p_Subst1);
2228    l_temp := replace(l_temp, '<p2>', p_Subst2);
2229    l_temp := replace(l_temp, '<p3>', p_Subst3);
2230    return l_temp;
2231 end;
2232 
2233 --------------------------------------------------------------------------------
2234 -- Name:        EscapeURLParam
2235 --
2236 -- Description:
2237 --
2238 -- Parameters:
2239 --
2240 --------------------------------------------------------------------------------
2241 function EscapeURLParam(p_param in varchar2) return varchar2 is
2242    l_temp varchar2(1000) := p_param;
2243 begin
2244       l_temp := replace(l_temp, '%', '%25');
2245       l_temp := replace(l_temp, ' ', '%20');
2246       l_temp := replace(l_temp, '+', '%2B');
2247       l_temp := replace(l_temp, '"', '%22');
2248       l_temp := replace(l_temp, '#', '%23');
2249       l_temp := replace(l_temp, '&', '%26');
2250    return l_temp;
2251 end;
2252 
2253 --------------------------------------------------------------------------------
2254 -- Name:        GetUser
2255 --
2256 -- Description: Return the current user, or CGI REMOTE_USER setting if defined
2257 --
2258 -- Parameters:  None
2259 --
2260 --------------------------------------------------------------------------------
2261 function GetUser return varchar2 is
2262    remote_user varchar2(30);
2263 begin
2264    begin
2265       remote_user := upper(owa_util.get_cgi_env('REMOTE_USER'));
2266    exception
2267       when others then
2268          remote_user := null;
2269    end;
2270    return nvl(remote_user, user);
2271 end;
2272 
2273 --------------------------------------------------------------------------------
2274 -- Name:
2275 --
2276 -- Description:
2277 --
2278 -- Parameters:
2279 --
2280 --------------------------------------------------------------------------------
2281 procedure RegisterURL(p_url in varchar2) is
2282    port_number varchar2(10) := ltrim(rtrim(owa_util.get_cgi_env('SERVER_PORT')));
2283 begin
2284    if p_url is null then
2285       URLComplete := true;
2286    elsif not URLComplete then
2287       CurrentURL := 'http://'||owa_util.get_cgi_env('SERVER_NAME');
2288       if port_number is not null then
2289          CurrentURL := CurrentURL||':'||port_number;
2290       end if;
2291       CurrentURL := CurrentURL||owa_util.get_cgi_env('SCRIPT_NAME')||'/'||p_url;
2292    end if;
2293 exception
2294    when others then
2295       raise_application_error(-20000, 'XNP_WSGL.RegisterURL<br>'||SQLERRM);
2296 
2297 end;
2298 
2299 --------------------------------------------------------------------------------
2300 -- Name:
2301 --
2302 -- Description:
2303 --
2304 -- Parameters:
2305 --
2306 --------------------------------------------------------------------------------
2307 function NotLowerCase return boolean is
2308 begin
2309    URLComplete := true;
2310    if (owa_util.get_cgi_env('PATH_INFO') <> lower(owa_util.get_cgi_env('PATH_INFO')))then
2311       htp.htmlOpen;
2312       htp.headOpen;
2313       RefreshURL;
2314       htp.headClose;
2315       htp.htmlClose;
2316       return true;
2317    end if;
2318    return false;
2319 exception
2320    when others then
2321 
2322       raise_application_error(-20000, 'XNP_WSGL.NotLowerCase<br>'||SQLERRM);
2323       return true;
2324 end;
2325 
2326 --------------------------------------------------------------------------------
2327 -- Name:
2328 --
2329 -- Description:
2330 --
2331 -- Parameters:
2332 --
2333 --------------------------------------------------------------------------------
2334 procedure RefreshURL is
2335 begin
2336    htp.p('<META HTTP-EQUIV="Refresh" CONTENT="0;URL='||CurrentURL||'">');
2337 exception
2338    when others then
2339       raise_application_error(-20000, 'XNP_WSGL.RefreshURL<br>'||SQLERRM);
2340 end;
2341 
2342 --------------------------------------------------------------------------------
2343 -- Name:
2344 --
2345 -- Description:
2346 --
2347 -- Parameters:
2348 --
2349 --------------------------------------------------------------------------------
2350 function ExternalCall(p_proc in varchar2) return boolean is
2351    path_info     varchar2(1000):= substr(owa_util.get_cgi_env('PATH_INFO'),2);
2352    http_referrer varchar2(1000);
2353    pos_host      number;
2354    pos_script    number;
2355    pos_modname   number;
2356    pos_dollar    number;
2357 begin
2358    URLComplete := true;
2359    -- if this procedue is not the one in URL, then it must have been called
2360    -- directly as a procedure call, so just return false
2361    if (lower(p_proc) <> lower(substr(owa_util.get_cgi_env('PATH_INFO'),2))) then
2362       return false;
2363    end if;
2364    http_referrer := owa_util.get_cgi_env('HTTP_REFERER');
2365    if http_referrer is null then
2366       http_referrer := owa_util.get_cgi_env('HTTP_REFERRER');
2367    end if;
2368    -- some browsers store octal values for non alphanumerics in env vars
2369    http_referrer := replace(http_referrer,'%24','$');
2370 
2371    pos_host := instr(http_referrer, '//'||owa_util.get_cgi_env('SERVER_NAME'));
2372    pos_script := instr(http_referrer, owa_util.get_cgi_env('SCRIPT_NAME'));
2373    pos_dollar := instr(path_info,'$');
2374    pos_modname := instr(lower(http_referrer), lower(substr(path_info, 1, pos_dollar)));
2375    if (pos_host <> 0 and pos_script > pos_host and pos_modname > pos_script) then
2376       return false;
2377    else
2378       DisplayMessage(MESS_ERROR, MsgGetText(231,XNP_WSGLM.MSG231_ACCESS_DENIED));
2379       return true;
2380    end if;
2381 exception
2382    when others then
2383       raise_application_error(-20000, 'XNP_WSGL.ExternalCall<br>'||SQLERRM);
2384       return true;
2385 end;
2386 
2387 --------------------------------------------------------------------------------
2388 -- Name:
2389 --
2390 -- Description:
2391 --
2392 -- Parameters:
2393 --
2394 --------------------------------------------------------------------------------
2395 function CalledDirect(p_proc in varchar2) return boolean is
2396 begin
2397    URLComplete := true;
2398    if (lower(p_proc) = lower(substr(owa_util.get_cgi_env('PATH_INFO'),2))) then
2399       DisplayMessage(MESS_ERROR, MsgGetText(231,XNP_WSGLM.MSG231_ACCESS_DENIED));
2400       return true;
2401    else
2402       return false;
2403    end if;
2404 exception
2405    when others then
2406       raise_application_error(-20000, 'XNP_WSGL.CalledDirect<br>'||SQLERRM);
2407       return true;
2408 end;
2409 
2410 --------------------------------------------------------------------------------
2411 -- Name:
2412 --
2413 -- Description:
2414 --
2415 -- Parameters:
2416 --
2417 --------------------------------------------------------------------------------
2418 procedure AddURLParam(p_paramname in varchar2,
2419                       p_paramval in varchar2) is
2420 begin
2421    if p_paramname is not null and not URLComplete then
2422       if instr(CurrentURL,'?') = 0 then
2423          CurrentURL := CurrentURL || '?';
2424       else
2425          CurrentURL := CurrentURL || '&';
2426       end if;
2427       CurrentURL := CurrentURL || p_paramname || '=' || EscapeURLParam(p_paramval);
2428    end if;
2429 exception
2430    when others then
2431       raise_application_error(-20000, 'XNP_WSGL.AddURLParam<br>'||SQLERRM);
2432 end;
2433 
2434 --------------------------------------------------------------------------------
2435 -- Name:
2436 --
2437 -- Description:
2438 --
2439 -- Parameters:
2440 --
2441 --------------------------------------------------------------------------------
2442 procedure AddURLParam(p_paramname in varchar2,
2443                       p_paramval in typString240Table) is
2444    i number := 1;
2445 begin
2446    while true loop
2447       AddURLParam(p_paramname, p_paramval(i));
2448       i := i+1;
2449    end loop;
2450 exception
2451    when no_data_found then
2452       null;
2453    when others then
2454       raise_application_error(-20000, 'XNP_WSGL.AddURLParam2<br>'||SQLERRM);
2455 end;
2456 
2457 --------------------------------------------------------------------------------
2458 -- Name:
2459 --
2460 -- Description:
2461 --
2462 -- Parameters:
2463 --
2464 --------------------------------------------------------------------------------
2465 procedure StoreURLLink(p_level in number,
2466                        p_caption in varchar2,
2467                        p_open in boolean,
2468                        p_close in boolean) is
2469    thisCookie       owa_cookie.cookie;
2470    modname          varchar2(30);
2471 begin
2472    modname := substr(owa_util.get_cgi_env('PATH_INFO'),2,30);
2473    modname := upper( substr(modname, 1, instr(modname,'$')) );
2474    if not URLCookieSet and LayNumberOfPages = 0 then
2475       if p_open then
2476          owa_util.mime_header('text/html',FALSE);
2477       end if;
2478       if p_level is not null then
2479          owa_cookie.send('WSG$'||modname||'URL'||to_char(p_level),
2480                          CurrentURL,
2481                          null,
2482                          owa_util.get_cgi_env('SCRIPT_NAME'),
2483                          owa_util.get_cgi_env('SERVER_NAME'));
2484          owa_cookie.send('WSG$'||modname||'CAP'||to_char(p_level),
2485                          replace(p_caption,' ','_'),
2486                          null,
2487                          owa_util.get_cgi_env('SCRIPT_NAME'),
2488                          owa_util.get_cgi_env('SERVER_NAME'));
2489       end if;
2490       if p_close then
2491          owa_util.http_header_close;
2492       end if;
2493    end if;
2494    if p_close then
2495       URLCookieSet := true;
2496    end if;
2497 exception
2498    when others then
2499       raise_application_error(-20000, 'XNP_WSGL.StoreURLLink<br>'||SQLERRM);
2500 end;
2501 
2502 --------------------------------------------------------------------------------
2503 -- Name:
2504 --
2505 -- Description:
2506 --
2507 -- Parameters:
2508 --
2509 --------------------------------------------------------------------------------
2510 procedure ReturnLinks(p_levels in varchar2, p_style in number) is
2511    URLCookie  owa_cookie.cookie;
2512    CaptionCookie owa_cookie.cookie;
2513    any_done   boolean := false;
2514    modname    varchar2(30);
2515    l_levels   varchar2(100) := '.'||p_levels;
2516    next_level varchar2(3);
2517    pos        number;
2518 begin
2519    if LayNumberOfPages = 1 then
2520       modname := substr(owa_util.get_cgi_env('PATH_INFO'),2,30);
2521       modname := upper( substr(modname, 1, instr(modname,'$')) );
2522       while l_levels is not null loop
2523          pos := instr(l_levels,'.',-1);
2524          next_level := substr(l_levels, pos+1);
2525          l_levels := substr(l_levels, 1, pos-1);
2526          URLCookie := owa_cookie.get('WSG$'||modname||'URL'||next_level);
2527          CaptionCookie := owa_cookie.get('WSG$'||modname||'CAP'||next_level);
2528          if (nvl(URLCookie.num_vals,0) > 0) and (nvl(CaptionCookie.num_vals,0) > 0) then
2529             if not any_done then
2530                NavLinks(p_style, MsgGetText(20,XNP_WSGLM.CAP020_RETURN_LINKS), 0);
2531                any_done := true;
2532 
2533             end if;
2534             NavLinks(p_style, replace(CaptionCookie.vals(1),'_',' '), 1, URLCookie.vals(1));
2535          end if;
2536       end loop;
2537    end if;
2538 exception
2539    when others then
2540       raise_application_error(-20000, 'XNP_WSGL.ReturnLinks'||'<br>'||SQLERRM);
2541 end;
2542 
2543 --------------------------------------------------------------------------------
2544 -- Name:
2545 --
2546 -- Description:
2547 --
2548 -- Parameters:
2549 --
2550 --------------------------------------------------------------------------------
2551 function Checksum(p_buff in varchar2) return number is
2552    l_sum number default 0;
2553    l_n   number;
2554 begin
2555    for i in 1 .. trunc(length(p_buff||'x'||p_buff)/2) loop
2556       l_n := ascii(substr(p_buff||'x'||p_buff, i*2-1, 1))*256 +
2557              ascii(substr(p_buff||'x'||p_buff, i*2, 1));
2558       l_sum := mod(l_sum+l_n,4294967296);
2559    end loop;
2560    while ( l_sum > 65536 ) loop
2561       l_sum := bitand( l_sum, 65535 ) + trunc(l_sum/65536);
2562    end loop;
2563    return l_sum;
2564 end;
2565 
2566 --------------------------------------------------------------------------------
2567 -- Name:
2568 --
2569 -- Description:
2570 --
2571 -- Parameters:
2572 --
2573 --------------------------------------------------------------------------------
2574 function ValidateChecksum(p_buff in varchar2, p_checksum in varchar2)
2575          return boolean is
2576 begin
2577    if (nvl(to_number(p_checksum),-1) <> Checksum(p_buff)) then
2578       DisplayMessage(MESS_ERROR, MsgGetText(231,XNP_WSGLM.MSG231_ACCESS_DENIED));
2579       return false;
2580    else
2581       return true;
2582    end if;
2583 end;
2584 
2585 --------------------------------------------------------------------------------
2586 -- Name:        EscapeURLParam
2587 --
2588 -- Description:
2589 --
2590 -- Parameters:
2591 --
2592 --------------------------------------------------------------------------------
2593 function EscapeURLParam(p_param in varchar2,
2594                         p_space in boolean,
2595                         p_plus in boolean,
2596                         p_percent in boolean,
2597                         p_doublequote in boolean,
2598                         p_hash in boolean,
2599                         p_ampersand in boolean) return varchar2 is
2600    l_temp varchar2(1000) := p_param;
2601 begin
2602    if p_percent then
2603       l_temp := replace(l_temp, '%', '%25');
2604    end if;
2605    if p_space then
2606       l_temp := replace(l_temp, ' ', '%20');
2607    end if;
2608    if p_plus then
2609       l_temp := replace(l_temp, '+', '%2B');
2610    end if;
2611    if p_doublequote then
2612       l_temp := replace(l_temp, '"', '%22');
2613    end if;
2614    if p_hash then
2615       l_temp := replace(l_temp, '#', '%23');
2616    end if;
2617    if p_ampersand then
2618       l_temp := replace(l_temp, '&', '%26');
2619    end if;
2620    return l_temp;
2621 end;
2622 
2623 --------------------------------------------------------------------------------
2624 -- Name:        PageHeader
2625 --
2626 -- Description: Provided for backward compatibility with R1.3
2627 --
2628 -- Parameters:  p_title      IN   Page Title caption
2629 --              p_header     IN   Page Header caption
2630 --              p_background IN   Background gif file, if any
2631 --      p_center     IN   Centre Alignment
2632 --
2633 --------------------------------------------------------------------------------
2634 procedure PageHeader(p_title in varchar2,
2635                      p_header in varchar2,
2636                      p_background in varchar2,
2637 
2638                      p_center in boolean) is
2639   l_attributes varchar2(100) := null;
2640 begin
2641    if (p_title <> p_header) then
2642       DefinePageHead(p_title||' : '||p_header);
2643    else
2644       DefinePageHead(p_title);
2645    end if;
2646    if p_background is not null then
2647       l_attributes := 'BACKGROUND="' || p_background || '"';
2648    end if;
2649    OpenPageBody(p_center, l_attributes);
2650    DefaultPageCaption(p_header);
2651 end;
2652 
2653 --------------------------------------------------------------------------------
2654 -- Name:        PageFooter
2655 --
2656 -- Description: Provided for backward compatibility with R1.3
2657 --
2658 -- Parameters:  None
2659 --
2660 --------------------------------------------------------------------------------
2661 procedure PageFooter is
2662 begin
2663    ClosePageBody;
2664 end;
2665 
2666 --------------------------------------------------------------------------------
2667 -- Name:        RowContext
2668 --
2669 -- Description: Provided for backward compatibility with R1.3
2670 --
2671 -- Parameters:  p_context   IN  The context string
2672 --
2673 --------------------------------------------------------------------------------
2674 procedure RowContext(p_context in varchar2) is
2675 begin
2676    htp.header(2, p_context);
2677 end;
2678 
2679 --------------------------------------------------------------------------------
2680 -- Name:        MAX_ROWS_MESSAGE
2681 --
2682 -- Description: Provided for backward compatibility with R1.3 (Was a varchar2
2683 --              constant in R1.3, but now accesses WSGLM text)
2684 --
2685 -- Parameters:  None
2686 --
2687 
2688 --------------------------------------------------------------------------------
2689 function MAX_ROWS_MESSAGE return varchar2 is
2690 begin
2691    return MsgGetText(203,XNP_WSGLM.MSG203_MAX_ROWS,to_char(MAX_ROWS));
2692 end;
2693 end;