Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtprintinfo / UI / DtFindD.C
1 /* $TOG: DtFindD.C /main/5 1998/07/24 16:12:13 mgreess $ */
2 /*                                                                      *
3  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
4  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
5  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
6  * (c) Copyright 1993, 1994 Novell, Inc.                                *
7  */
8
9 #include "DtFindD.h"
10 #include "DtMainW.h"
11 #include "DtApp.h"
12 #include "DtSetModList.h"
13 #include "DtWorkArea.h"
14 #include "Button.h"
15 #include "Prompt.h"
16 #include "LabelObj.h"
17 #include "Container.h"
18 #include "Sep.h"
19 #include "DtPrtJobIcon.h"
20
21 #include "dtprintinfomsg.h"
22
23 #include <unistd.h> // This is for the getuid function
24
25 DtJobList::DtJobList(AnyUI *parent)
26         : Container(parent, "found_container", SCROLLED_VERTICAL_ROW_COLUMN,
27                     MULTIPLE_SELECT)
28 {
29    IconView(SMALL_ICON);
30 }
31
32 class _JobIcon : public IconObj
33 {
34  public:
35    DtPrtJobIcon *job_icon;
36    BaseUI *printer;
37    BaseUI *job_list;
38
39    _JobIcon(AnyUI *parent, DtPrtJobIcon *obj, IconFields);
40 };
41
42 _JobIcon::_JobIcon(AnyUI *parent, DtPrtJobIcon *obj, IconFields fields)
43         : IconObj(parent, (char *)obj->Name(), "DtPrtjb", NULL, NULL, NULL,
44                   fields)
45 {
46    job_icon = obj;
47    job_list = obj->Parent();
48    printer = job_list->Parent();
49 }
50
51 void DtJobList::NotifySelected(BaseUI *obj)
52 {
53    Container::NotifySelected(obj);
54
55    int n_items;
56    Selection(&n_items);
57    DtFindD *findD = (DtFindD *) Parent();
58    if (n_items == 0)
59     {
60       findD->cancel_jobs->Active(false);
61       findD->goto_job->Active(false);
62     }
63    else
64     {
65       if (n_items == 1)
66          findD->goto_job->Active(true);
67       else
68          findD->goto_job->Active(false);
69       findD->cancel_jobs->Active(true);
70     }
71 }
72
73 DtFindD::DtFindD(MotifUI *parent,
74                  char *name,
75                  SelectProc select_proc)
76         : Dialog(parent, name)
77 {
78    _has_been_posted = false;
79
80    mainw = (DtMainW *) parent;
81    _select_proc = select_proc;
82    if (getuid() == 0) // check to see if we are root
83       prompt = new Prompt(this, MESSAGE(JobName1L));
84    else
85       prompt = new Prompt(this, MESSAGE(MyJobNameL));
86    prompt->AttachRight();
87    prompt->AttachLeft();
88    prompt->AttachTop();
89
90    Container *rc = new Container(this, "rc", HORIZONTAL_ROW_COLUMN,
91                                  MULTIPLE_SELECT);
92    if (getuid() == 0) // check to see if we are root
93       match_any_user = new Button(rc, MESSAGE(OnlyRootJobsL), TOGGLE_BUTTON);
94    else
95       match_any_user = NULL;
96    ignore_case = new Button(rc, MESSAGE(IgnoreCaseL), TOGGLE_BUTTON);
97    ignore_case->Selected(true);
98    exact_match = new Button(rc, MESSAGE(ExactMatchL), TOGGLE_BUTTON);
99    rc->AttachRight();
100    rc->AttachTop(prompt, 5);
101
102    Sep *sep = new Sep(this);
103    sep->AttachRight();
104    sep->AttachLeft();
105
106    sep->AttachTop(rc, 5);
107
108    field1 = new LabelObj(this, MESSAGE(JobName1L));
109    field1->AttachLeft(22);
110    field1->AttachTop(sep, 5);
111    field2 = new LabelObj(this, MESSAGE(PrinterL));
112    field2->AttachLeft(field1);
113    field2->AttachTop(sep, 5);
114    field3 = new LabelObj(this, MESSAGE(OwnerL));
115    field3->AttachLeft(field2);
116    field3->AttachTop(sep, 5);
117    field3->Visible(false);
118    field4 = new LabelObj(this, MESSAGE(PositionL));
119    field4->AttachLeft(field2);
120    field4->AttachRight();
121    field4->AttachTop(sep, 5);
122
123    Container *form = new Container(this, "form", FORM);
124    goto_job = new Button(form, MESSAGE(GotoL), PUSH_BUTTON, GotoCB, this);
125    goto_job->Active(false);
126    cancel_jobs = new Button(form, MESSAGE(CancelPrintJobsL), PUSH_BUTTON,
127                             CancelJobsCB, this);
128    cancel_jobs->Active(false);
129    form->AttachBottom(5);
130    form->AttachRight();
131    form->AttachLeft();
132    goto_job->AttachBottom();
133    goto_job->AttachTop();
134    cancel_jobs->AttachBottom();
135    cancel_jobs->AttachTop();
136
137    found_container = new DtJobList(this);
138    found_container->AttachRight();
139    found_container->AttachLeft();
140    found_container->AttachBottom(form, 10);
141    found_container->AttachTop(field1);
142
143    start = new Button(this, MESSAGE(StartFindL), PUSH_BUTTON, StartCB, this);
144    stop = new Button(this, MESSAGE(StopFindL), PUSH_BUTTON, StopCB, this);
145    close_it = new Button(this, MESSAGE(CloseL), PUSH_BUTTON, CancelCB, this);
146    stop->Active(false);
147    help = new Button(this, MESSAGE(HelpL), PUSH_BUTTON, HelpCB, this);
148
149    DefaultButton(start);
150    CancelButton(close_it);
151 }
152
153 DtFindD::~DtFindD()
154 {
155    // Empty
156 }
157
158 boolean DtFindD::SetVisiblity(boolean flag)
159 {
160    if (_has_been_posted == false)
161     {
162       Dialog::SetVisiblity(flag);
163       Refresh();
164       int width = StringWidth(Name()) + 30;
165       if (width < 400)
166          width = 400;
167       if (Width() < width)
168          Width(width);
169       _has_been_posted = true;
170       int w1 = cancel_jobs->Width();
171       int w2 = goto_job->Width();
172       int offset = (width - (w1 + w2)) / 3;
173       goto_job->AttachLeft(offset);
174       cancel_jobs->AttachRight(offset);
175       cancel_jobs->AttachLeft(NULL, 0);
176     }
177    found_container->DeleteChildren();
178    cancel_jobs->Active(false);
179    goto_job->Active(false);
180    if (match_any_user)
181     {
182       match_any_user->Selected(false);
183       match_any_user->Active(mainw->setPrefD->ShowOnlyMyJobs() ? false : true);
184     }
185    Dialog::SetVisiblity(flag);
186    if (flag)
187       prompt->SetFocus();
188    return true;
189 }
190
191 void DtFindD::UpdateMatchAnyUser()
192 {
193    if (match_any_user)
194       match_any_user->Active(mainw->setPrefD->ShowOnlyMyJobs() ? false : true);
195 }
196
197 boolean DtFindD::MatchAnyUser()
198 {
199    if (match_any_user)
200     {
201       if (match_any_user->Active() == false)
202          return false;
203       else
204          return (match_any_user->Selected() ? false : true);
205     }
206    else
207       return false;
208 }
209
210 void DtFindD::Start()
211 {
212    _working = true;
213    mainw->in_find = true;
214    mainw->WorkingCursor(true);
215    stop->PointerShape(LEFT_SLANTED_ARROW_CURSOR);
216    help->PointerShape(LEFT_SLANTED_ARROW_CURSOR);
217    stop->Active(true);
218    DefaultButton(stop);
219    close_it->Active(false);
220    start->Active(false);
221    prompt->Active(false);
222    ignore_case->Active(false);
223    exact_match->Active(false);
224    found_container->DeleteChildren();
225    cancel_jobs->Active(false);
226    goto_job->Active(false);
227    if (match_any_user)
228       match_any_user->Active(false);
229    found_container->BeginUpdate();
230
231    _cur_obj = 0;
232    if (mainw->container->NumChildren())
233     {
234       BaseUI *icon = mainw->container->Children()[0];
235       _prev_visible = icon->Visible();
236       _prev_opened = icon->Open();
237     }
238    AddTimeOut(CheckQueue, NULL, 200);
239 }
240
241 void DtFindD::Cancel()
242 {
243    Visible(false);
244    Stop();
245 }
246
247 void DtFindD::Stop()
248 {
249    if (_cur_obj > mainw->container->NumChildren())
250       return;
251    _cur_obj = mainw->container->NumChildren() + 1;
252    found_container->EndUpdate();
253    start->Active(true);
254    DefaultButton(start);
255    stop->Active(false);
256    close_it->Active(true);
257    prompt->Active(true);
258    ignore_case->Active(true);
259    exact_match->Active(true);
260    prompt->SetFocus();
261    if (mainw->setModList && mainw->setModList->Visible())
262       mainw->setModList->Reset();
263    if (match_any_user)
264       match_any_user->Active(mainw->setPrefD->ShowOnlyMyJobs() ? false : true);
265    if (Visible())
266     {
267        int n_matches;
268        BaseUI **matches;
269        char *value1 = NULL;
270        char *value = prompt->Value();
271        if (!value || *value == '\0')
272           value = ".*";
273        else if (*value == '*')
274         {
275           value1 = new char[strlen(value) + 2];
276           sprintf(value1, ".%s", value);
277           value = value1;
278         }
279        mainw->container->FindByName(value, 0, &n_matches, &matches,
280                                     _select_proc,
281                                     exact_match->Selected() ? false : true,
282                                     ignore_case->Selected() ? false : true);
283        delete [] value1;
284        if (n_matches)
285         {
286           IconFields fields = new IconFieldsRec;
287           int n_fields, i, w;
288
289           if (MatchAnyUser())
290              n_fields = 3;
291           else
292              n_fields = 2;
293           fields->n_fields = n_fields;
294           fields->field_spacing = 20;
295           fields->fields = new char *[n_fields]; 
296           fields->fields_widths = new int[n_fields];
297           fields->alignments = new LabelType[n_fields];
298           fields->draw_fields = NULL;
299           fields->selected = NULL;
300           fields->active = NULL;
301
302           fields->name_width = StringWidth(MESSAGE(JobName1L));
303           fields->fields_widths[0] = StringWidth(MESSAGE(PrinterL));
304           fields->alignments[0] = LEFT_JUSTIFIED;
305           if (n_fields == 3)
306            {
307              fields->fields_widths[1] = StringWidth(MESSAGE(OwnerL));
308              fields->fields_widths[2] = StringWidth(MESSAGE(PositionL));
309              fields->alignments[1] = LEFT_JUSTIFIED;
310              fields->alignments[2] = RIGHT_JUSTIFIED;
311              if (field3->Visible() == false)
312               {
313                 field3->Visible(true);
314                 field4->AttachLeft(field3);
315               }
316            }
317           else
318            {
319              fields->alignments[1] = RIGHT_JUSTIFIED;
320              fields->fields_widths[1] = StringWidth(MESSAGE(PositionL));
321              if (field4->Visible())
322               {
323                 field4->AttachLeft(field2);
324                 field3->Visible(false);
325               }
326            }
327           for (i = 0; i < n_matches; i++)
328            {
329              DtPrtJobIcon *job = (DtPrtJobIcon *)matches[i];
330              if ((w = StringWidth(job->Name())) > fields->name_width)
331                 fields->name_width = w;
332              w = StringWidth(job->Parent()->Parent()->Name());
333              if (w > fields->fields_widths[0])
334                 fields->fields_widths[0] = w;
335              if (n_fields == 3)
336               {
337                 char *s = job->PrintJobObj()->AttributeValue((char *)OWNER);
338                 if ((w = StringWidth(s)) > fields->fields_widths[1])
339                    fields->fields_widths[1] = w;
340               }
341            }
342           if (fields->name_width % 2)
343              fields->name_width += 1;
344
345           if (fields->fields_widths[0] % 2)
346              fields->fields_widths[0] += 1;
347
348           if (n_fields == 3)
349            {
350              if (fields->fields_widths[1] % 2)
351                 fields->fields_widths[1] += 1;
352              if (fields->fields_widths[2] % 2)
353                 fields->fields_widths[2] += 1;
354            }
355           else
356            {
357              if (fields->fields_widths[1] % 2)
358                 fields->fields_widths[1] += 1;
359            }
360
361           field1->Width(fields->name_width + 20);
362           field2->Width(fields->fields_widths[0] + 20);
363           field3->Width(fields->fields_widths[1] + 20);
364           if (n_fields == 3)
365              field4->Width(fields->fields_widths[2] + 20);
366
367           for (i = 0; i < n_matches; i++)
368            {
369              DtPrtJobIcon *job = (DtPrtJobIcon *)matches[i];
370              char number[9];
371              sprintf(number, "%d", job->Order() + 1);
372              fields->fields[0] = (char *)job->Parent()->Parent()->Name();
373              if (n_fields == 3)
374               {
375                 char *s = job->PrintJobObj()->AttributeValue((char *)OWNER);
376                 fields->fields[1] = s;
377                 fields->fields[2] = number;
378               }
379              else
380                 fields->fields[1] = number;
381              _JobIcon *icon = new _JobIcon(found_container, job, fields);
382            }
383           delete []matches;
384           delete fields->fields;
385           delete fields->fields_widths;
386           delete fields->alignments;
387           delete fields;
388         }
389        else
390           new LabelObj(found_container, MESSAGE(NoMatchesL));
391     }
392    mainw->WorkingCursor(false);
393    _working = false;
394    mainw->in_find = false;
395 }
396
397 void DtFindD::UpdateQueue()
398 {
399    if (_cur_obj < mainw->container->NumChildren())
400     {
401       BaseUI *icon = mainw->container->Children()[_cur_obj];
402       char *message = new char[200];
403       sprintf(message, MESSAGE(SearchL), icon->Name());
404       found_container->UpdateMessage(message);
405       delete [] message;
406       icon->Visible(true);
407       DtPrinterIcon *icon1 = (DtPrinterIcon *)icon;
408       icon1->waitForChildren = true;
409       icon1->Open(true);
410       icon1->waitForChildren = false;
411       boolean no_children;
412       if (icon1->QueueObj()->NumChildren() == 0)
413          no_children = true;
414       else
415        {
416          int n_matches;
417          char *value1 = NULL;
418          char *value = prompt->Value();
419          if (!value || *value == '\0')
420             value = ".*";
421          else if (*value == '*')
422           {
423             value1 = new char[strlen(value) + 2];
424             sprintf(value1, ".%s", value);
425             value = value1;
426           }
427          icon1->FindByName(value, 0, &n_matches, NULL, _select_proc,
428                            exact_match->Selected() ? false : true,
429                            ignore_case->Selected() ? false : true);
430          delete value1;
431          if (n_matches)
432             no_children = false;
433          else
434             no_children = true;
435        }
436       if (no_children)
437        {
438          if (_prev_visible == false)
439             icon->Visible(false);
440          if (_prev_opened == false)
441             icon->Open(false);
442        }
443       _cur_obj++;
444       if (_cur_obj < mainw->container->NumChildren())
445        {
446          icon = mainw->container->Children()[_cur_obj];
447          _prev_visible = icon->Visible();
448          _prev_opened = icon->Open();
449        }
450       AddTimeOut(CheckQueue, NULL, 200);
451     }
452    else if (_cur_obj == mainw->container->NumChildren())
453       Stop();
454 }
455
456 boolean DtFindD::HandleHelpRequest()
457 {
458    mainw->DisplayHelp("FindDialogDE");
459    return true;
460 }
461
462 void DtFindD::CheckQueue(BaseUI *obj, void *)
463 {
464    ((DtFindD *)obj)->UpdateQueue(); 
465 }
466
467 BaseUI *DtFindD::FindJob(BaseUI *obj)
468 {
469    int i;
470    BaseUI *job = ((_JobIcon *)obj)->job_icon;
471    BaseUI **children = ((_JobIcon *)obj)->job_list->Children();
472    int n_children = ((_JobIcon *)obj)->job_list->NumChildren();
473    for (i = 0; i < n_children; i++)
474       if (job == children[i])
475          return children[i];
476    Dialog *dialog = new Dialog(mainw, (char *) Name(),
477                                MESSAGE(NotFoundMessageL), INFORMATION,
478                                MESSAGE(OKL));
479    dialog->Visible(true);
480    return NULL;
481 }
482
483 void DtFindD::GotoCB(void *data)
484 {
485    DtFindD *obj = (DtFindD *) data;
486    BaseUI **selection;
487    int n_items;
488    obj->found_container->Selection(&n_items, &selection);
489    if (n_items == 1)
490     {
491       BaseUI *print_job = obj->FindJob(selection[0]);
492       if (print_job)
493        {
494          print_job->MakeVisible();
495          print_job->Selected(true);
496        }
497     }
498    delete []selection;
499 }
500
501 void DtFindD::CancelJobsCB(void *data)
502 {
503    DtFindD *obj = (DtFindD *) data;
504    extern void ActionCB(void *data, BaseUI *obj, char *actionReferenceName);
505
506    BaseUI **selection;
507    int n_items;
508    obj->found_container->Selection(&n_items, &selection);
509    if (n_items)
510     {
511       int i;
512       for (i = 0; i < n_items; i++)
513        {
514          BaseUI *print_job = obj->FindJob(selection[i]);
515          if (print_job)
516           {
517             DtApp *app = (DtApp *)obj->mainw->Parent();
518             app->ActionCB(print_job, (char *)CANCEL_PRINT_JOB);
519           }
520        }
521     }
522    delete []selection;
523 }
524
525 void DtFindD::CloseCB()
526 {
527    Cancel();
528 }
529
530 void DtFindD::CancelCB(void *data)
531 {
532    DtFindD *obj = (DtFindD *) data;
533    obj->Cancel();
534 }
535
536 void DtFindD::StartCB(void *data)
537 {
538    DtFindD *obj = (DtFindD *) data;
539    obj->Start();
540 }
541
542 void DtFindD::StopCB(void *data)
543 {
544    DtFindD *obj = (DtFindD *) data;
545    obj->_cur_obj = obj->mainw->container->NumChildren();
546 }
547
548 void DtFindD::HelpCB(void *data)
549 {
550    DtFindD *obj = (DtFindD *) data;
551    obj->HandleHelpRequest();
552 }
553
554 void DtFindD::DeleteJobFromList(BaseUI *obj)
555 {
556    int i;
557    int n_children = found_container->NumChildren();
558    _JobIcon **children = (_JobIcon **)found_container->Children();
559    for (i = 0; i < n_children; i++)
560     {
561       if (obj->Parent() == children[i]->job_list)
562        {
563          if (children[i]->job_icon == obj)
564           {
565             children[i]->Selected(false);
566             delete children[i];
567             return;
568           }
569        }
570     }
571 }
572
573 void DtFindD::UpdatePrinter(BaseUI *printer)
574 {
575    int n_children = found_container->NumChildren();
576    if (n_children == 0)
577       return;
578
579    _JobIcon **children = (_JobIcon **)found_container->Children();
580    int i, w1;
581    int width = StringWidth(MESSAGE(PrinterL));
582    BaseUI *last_printer = NULL;
583    for (i = 0; i < n_children; i++)
584     {
585       if (last_printer != children[i]->printer)
586        {
587          last_printer = children[i]->printer;
588          if ((w1 = StringWidth(last_printer->Name())) > width)
589             width = w1;
590        }
591     }
592    if (width % 2)
593       width += 1;
594
595    // Create a widget and resize it to the desired width, then resize the
596    // row column to the width + margin space.  I have to do this because
597    // the row column widget does not resize itself correctly.
598    Dimension wid;
599    XtVaGetValues(found_container->InnerWidget(), XmNwidth, &wid, NULL);
600    wid -= field2->Width();
601    wid += width;
602    new LabelObj(found_container, " ");
603    children = (_JobIcon **)found_container->Children();
604    children[n_children]->Order(0);
605    n_children++;
606    children[0]->Width((int)wid);
607    wid += 6;
608    XtVaSetValues(found_container->InnerWidget(), XmNwidth, (int)wid, NULL);
609
610    field2->Width(width + 20);
611    for (i = 1; i < n_children; i++)
612     {
613       if (printer == children[i]->printer)
614          children[i]->Field(0, (char *)printer->Name(), width);
615       else
616          children[i]->Field(0, NULL, width);
617     }
618    delete children[0];
619 }
620
621 void DtFindD::UpdatePositions(BaseUI *printer)
622 {
623    if (mainw->in_find)
624       return;
625
626    int n_children = found_container->NumChildren();
627    if (n_children == 0)
628       return;
629
630    _JobIcon **children = (_JobIcon **)found_container->Children();
631    int i, index = children[0]->NumberFields() - 1;
632    for (i = 0; i < n_children; i++)
633     {
634       if (printer == children[i]->printer)
635          children[i]->Field(index, children[i]->job_icon->TopString(), 0);
636     }
637 }