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