Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
ActiveWindow.cpp
Go to the documentation of this file.
1 /* Project nGenEx
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: nGenEx.lib
6  FILE: ActiveWindow.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Window class
13 */
14 
15 #include <vector>
16 #include "MemDebug.h"
17 #include "ActiveWindow.h"
18 #include "EventDispatch.h"
19 #include "Color.h"
20 #include "Bitmap.h"
21 #include "Font.h"
22 #include "FontMgr.h"
23 #include "Layout.h"
24 #include "Polygon.h"
25 #include "Screen.h"
26 #include "View.h"
27 #include "Video.h"
28 
29 // +--------------------------------------------------------------------+
30 
34 
38 
39 // +--------------------------------------------------------------------+
40 
41 ActiveWindow::ActiveWindow(Screen* screen, int ax, int ay, int aw, int ah,
42 DWORD aid, DWORD s, ActiveWindow* pParent)
43 : Window(screen, ax, ay, aw, ah), id(aid), style(s), focus(false), enabled(true),
44 text_align(DT_CENTER), single_line(false), alpha(1),
45 texture(0), back_color(sys_back_color), fore_color(sys_fore_color),
46 parent(pParent), form(0), transparent(false), topmost(true),
47 layout(0), rows(1), cols(1), polys(0), vset(0), mtl(0),
48 fixed_width(0), fixed_height(0), hide_partial(true)
49 {
50  ZeroMemory(tab, sizeof(tab));
51 
52  font = sys_font;
53 
54  if (parent) {
55  parent->AddChild(this);
56  }
57  else {
58  screen->AddWindow(this);
59  }
60 
61  shown = false;
62  Show();
63 
64  char buf[32];
65  sprintf_s(buf, "ActiveWindow %d", id);
66  desc = buf;
67 }
68 
69 // +--------------------------------------------------------------------+
70 
72 {
73  if (layout) delete layout;
74 
75  screen->DelWindow(this);
76  Hide();
77  clients.destroy();
78  children.destroy();
79 
80  if (polys) delete [] polys;
81  if (vset) delete vset;
82  if (mtl) delete mtl;
83 }
84 
85 // +--------------------------------------------------------------------+
86 
87 void
89 {
91  if (dispatch)
92  dispatch->Register(this);
93 
94  ListIter<View> v_iter = view_list;
95  while (++v_iter) {
96  View* view = v_iter.value();
97  view->OnShow();
98  }
99 
101  while (++c_iter) {
102  ActiveWindow* child = c_iter.value();
103  child->Show();
104  }
105 
106  shown = true;
107 }
108 
109 // +--------------------------------------------------------------------+
110 
111 void
113 {
115  if (dispatch) {
116  dispatch->Unregister(this);
117  focus = false;
118  }
119 
120  ListIter<View> v_iter = view_list;
121  while (++v_iter) {
122  View* view = v_iter.value();
123  view->OnHide();
124  }
125 
127  while (++c_iter) {
128  ActiveWindow* child = c_iter.value();
129  child->Hide();
130  }
131 
132  shown = false;
133 }
134 
135 // +--------------------------------------------------------------------+
136 
137 void
139 {
140  if (rect.x == r.x &&
141  rect.y == r.y &&
142  rect.w == r.w &&
143  rect.h == r.h)
144  return;
145 
146  rect = r;
147  CalcGrid();
148 
150  while (++v)
151  v->OnWindowMove();
152 
153  if (layout)
154  layout->DoLayout(this);
155 }
156 
157 // +--------------------------------------------------------------------+
158 
159 void
161 {
162  if (child)
163  children.append(child);
164 }
165 
166 // +--------------------------------------------------------------------+
167 
168 void
170 {
171  if (layout)
172  layout->DoLayout(this);
173 }
174 
175 // +--------------------------------------------------------------------+
176 
177 void
178 ActiveWindow::UseLayout(const std::vector<DWORD>& min_x,
179 const std::vector<DWORD>& min_y,
180 const std::vector<float>& weight_x,
181 const std::vector<float>& weight_y)
182 {
183  if (!layout)
184  layout = new(__FILE__,__LINE__) Layout;
185 
186  if (layout)
187  layout->SetConstraints(min_x, min_y, weight_x, weight_y);
188 }
189 
190 void
191 ActiveWindow::UseLayout(const std::vector<float>& min_x,
192 const std::vector<float>& min_y,
193 const std::vector<float>& weight_x,
194 const std::vector<float>& weight_y)
195 {
196  if (!layout)
197  layout = new(__FILE__,__LINE__) Layout;
198 
199  if (layout)
200  layout->SetConstraints(min_x, min_y, weight_x, weight_y);
201 }
202 
203 void
205 int ncols,
206 int* min_x,
207 int* min_y,
208 float* weight_x,
209 float* weight_y)
210 {
211  if (!layout)
212  layout = new(__FILE__,__LINE__) Layout;
213 
214  if (layout)
215  layout->SetConstraints(nrows, ncols, min_x, min_y, weight_x, weight_y);
216 }
217 
218 // +--------------------------------------------------------------------+
219 
220 void
222 {
223  Draw();
224 }
225 
226 // +--------------------------------------------------------------------+
227 
228 Color
230 {
231  int ishade = (int) (shade * Color::SHADE_LEVELS);
232  return c.ShadeColor(ishade);
233 }
234 
235 // +--------------------------------------------------------------------+
236 
237 void
239 {
240  int w = rect.w;
241  int h = rect.h;
242 
243  if (w < 1 || h < 1 || !shown)
244  return;
245 
246  float old_alpha = alpha;
247 
248  if (!enabled)
249  SetAlpha(0.5);
250 
251  if (!transparent) {
252  if (texture && texture->Width()) {
253  DrawTextureGrid();
254  }
255  else {
256  FillRect(0, 0, w, h, ShadeColor(back_color, 1.0));
257  }
258  }
259 
260  if (enabled && view_list.size()) {
262  while (++v)
263  v->Refresh();
264  }
265 
266  if (!transparent) {
267  DrawStyleRect(0, 0, w, h, style);
268  }
269 
270  // draw text here:
271  DrawTabbedText();
272 
273  if (!enabled)
274  SetAlpha(old_alpha);
275 
276  // update children windows:
278  while (++iter) {
279  ActiveWindow* child = iter.value();
280  child->Draw();
281  }
282 }
283 
284 void
286 {
287  if (polys) delete [] polys;
288  if (vset) delete vset;
289  if (mtl) delete mtl;
290 
291  rows = 1;
292  cols = 1;
293 
294  if (!texture || texture->Width() < 1)
295  return;
296 
297  if (margins.left > 0) cols++;
298  if (margins.right > 0) cols++;
299  if (margins.top > 0) rows++;
300  if (margins.bottom > 0) rows++;
301 
302  int npolys = rows*cols;
303  int nverts = (rows+1) * (cols+1);
304 
305  if (style & WIN_FRAME_ONLY && npolys == 9)
306  npolys = 8; // skip the center poly
307 
308  if (npolys > 0) {
309  int i, j;
310  int x_offsets[4];
311  int y_offsets[4];
312  float u_offsets[4];
313  float v_offsets[4];
314 
315  x_offsets[0] = 0;
316  x_offsets[1] = margins.left ? margins.left : rect.w - margins.right;
317  x_offsets[2] = cols==2 ? rect.w : rect.w - margins.right;
318  x_offsets[3] = rect.w;
319 
320  y_offsets[0] = 0;
321  y_offsets[1] = margins.top ? margins.top : rect.h - margins.bottom;
322  y_offsets[2] = rows==2 ? rect.h : rect.h - margins.bottom;
323  y_offsets[3] = rect.h;
324 
325  float tex_w = (float) texture->Width();
326  float tex_h = (float) texture->Height();
327 
328  if (tex_w > rect.w) tex_w = (float) rect.w;
329  if (tex_h > rect.h) tex_h = (float) rect.h;
330 
331  u_offsets[0] = 0.0f;
332  u_offsets[1] = margins.left ? (float) margins.left : tex_w - (float) margins.right;
333  u_offsets[2] = cols==2 ? tex_w : tex_w - (float) margins.right;
334  u_offsets[3] = tex_w;
335 
336  v_offsets[0] = 0.0f;
337  v_offsets[1] = margins.top ? (float) margins.top : tex_h - (float) margins.bottom;
338  v_offsets[2] = rows==2 ? tex_h : tex_h - (float) margins.bottom;
339  v_offsets[3] = tex_h;
340 
341  tex_w = (float) texture->Width();
342  tex_h = (float) texture->Height();
343 
344  vset = new(__FILE__,__LINE__) VertexSet(nverts);
345 
346  int v = 0;
347 
348  Color c = Color::White;
349  c.SetAlpha((BYTE) (alpha*255));
350 
352 
353  for (i = 0; i <= rows; i++) {
354  for (j = 0; j <= cols; j++) {
355  vset->diffuse[v] = c.Value();
356 
357  vset->s_loc[v].x = (float) (rect.x + x_offsets[j]) - 0.5f;
358  vset->s_loc[v].y = (float) (rect.y + y_offsets[i]) - 0.5f;
359  vset->s_loc[v].z = 0.0f;
360  vset->rw[v] = 1.0f;
361 
362  vset->tu[v] = u_offsets[j] / tex_w;
363  vset->tv[v] = v_offsets[i] / tex_h;
364 
365  v++;
366  }
367  }
368 
369  mtl = new(__FILE__,__LINE__) Material;
371 
372  polys = new(__FILE__,__LINE__) Poly[npolys];
373 
374  Poly* p = polys;
375 
376  ZeroMemory(polys, npolys*sizeof(Poly));
377 
378  for (i = 0; i < rows; i++) {
379  for (j = 0; j < cols; j++) {
380  if (style & WIN_FRAME_ONLY) {
381  if (i == 1 && j == 1)
382  continue;
383  }
384 
385  p->nverts = 4;
386  p->vertex_set = vset;
387  p->material = mtl;
388 
389  p->verts[0] = (i+0)*(cols+1) + j;
390  p->verts[1] = (i+0)*(cols+1) + j + 1;
391  p->verts[2] = (i+1)*(cols+1) + j + 1;
392  p->verts[3] = (i+1)*(cols+1) + j;
393 
394  p++;
395  }
396  }
397  }
398 }
399 
400 void
402 {
403  int npolys = rows*cols;
404 
405  if (style & WIN_FRAME_ONLY && npolys == 9)
406  npolys = 8; // skip the center poly
407 
408  if (mtl) {
410  }
411 
412  int blend = Video::BLEND_SOLID;
413 
414  if (alpha < 1)
415  blend = Video::BLEND_ALPHA;
416 
417  Video* video = screen->GetVideo();
419  video->DrawScreenPolys(npolys, polys, blend);
421 }
422 
423 void
424 ActiveWindow::DrawStyleRect(const Rect& r, int style)
425 {
426  DrawStyleRect(r.x, r.y, r.x+r.w, r.y+r.h, style);
427 }
428 
429 void
430 ActiveWindow::DrawStyleRect(int x1, int y1, int x2, int y2, int style)
431 {
432  if (style & WIN_THIN_FRAME) {
433  DrawRect(x1,y1,x2-1,y2-1, ShadeColor(fore_color, 1.0));
434  }
435  else if (style & WIN_THICK_FRAME) {
436  DrawRect(x1+0,y1+0,x2-1,y2-1, ShadeColor(fore_color, 1.0));
437  DrawRect(x1+1,y1+1,x2-2,y2-2, ShadeColor(fore_color, 1.0));
438  DrawRect(x1+2,y1+2,x2-3,y2-3, ShadeColor(fore_color, 1.0));
439  }
440  else {
441  // draw bevel:
442  if ((style & WIN_RAISED_FRAME) && (style & WIN_SUNK_FRAME)) {
443  Color c = ShadeColor(back_color, 1.6); // full highlight
444  DrawLine(x1, y1, x2-1, y1, c);
445  DrawLine(x1, y1, x1, y2-1, c);
446 
447  c = ShadeColor(back_color, 1.3); // soft highlight
448  DrawLine(x1+1,y1+1, x2-2, y1+1, c);
449  DrawLine(x1+1,y1+1, x1+1, y2-2, c);
450 
451  c = ShadeColor(back_color, 0.6); // soft shadow
452  DrawLine(x2-2,y1+1, x2-2,y2-1, c);
453  DrawLine(x1+1,y2-2, x2-1,y2-2, c);
454 
455  c = ShadeColor(back_color, 0.3); // full shadow
456  DrawLine(x2-1,y1, x2-1,y2, c);
457  DrawLine(x1 ,y2-1, x2,y2-1, c);
458 
459  DrawRect(x1+4,y1+4, x2-5,y2-5, ShadeColor(back_color, 0.6)); // soft shadow
460  DrawRect(x1+5,y1+5, x2-6,y2-6, ShadeColor(back_color, 0.3)); // full shadow
461  DrawLine(x1+5,y2-6, x2-5,y2-6, ShadeColor(back_color, 1.3)); // soft highlight (bottom)
462  DrawLine(x2-6,y1+5, x2-6,y2-6, ShadeColor(back_color, 1.3)); // soft highlight (side)
463  DrawLine(x1+4,y2-5, x2-4,y2-5, ShadeColor(back_color, 1.6)); // soft highlight (bottom)
464  DrawLine(x2-5,y1+4, x2-5,y2-5, ShadeColor(back_color, 1.6)); // soft highlight (side)
465  }
466 
467  else if (style & WIN_RAISED_FRAME) {
468  Color c = ShadeColor(back_color, 1.6); // full highlight
469  DrawLine(x1, y1, x2-1, y1, c);
470  DrawLine(x1, y1, x1, y2-1, c);
471 
472  c = ShadeColor(back_color, 1.3); // soft highlight
473  DrawLine(x1+1,y1+1, x2-2, y1+1, c);
474  DrawLine(x1+1,y1+1, x1+1, y2-2, c);
475 
476  c = ShadeColor(back_color, 0.6); // soft shadow
477  DrawLine(x2-2,y1+1, x2-2,y2-1, c);
478  DrawLine(x1+1,y2-2, x2-1,y2-2, c);
479 
480  c = ShadeColor(back_color, 0.3); // full shadow
481  DrawLine(x2-1,y1, x2-1,y2, c);
482  DrawLine(x1 ,y2-1, x2,y2-1, c);
483  }
484 
485  else if (style & WIN_SUNK_FRAME) {
486  Color c = ShadeColor(back_color, 0.3); // full shadow
487  DrawLine(x1+1,y1+1, x1+1, y2, c);
488  DrawLine(x1+1,y1+1, x2, y1+1, c);
489 
490  c = ShadeColor(back_color, 0.6); // soft shadow
491  DrawLine(x1, y1, x1, y2, c);
492  DrawLine(x1, y1, x2, y1, c);
493 
494  c = ShadeColor(back_color, 1.3); // soft highlight
495  DrawLine(x2-2,y1+1, x2-2,y2-1, c);
496  DrawLine(x1+1,y2-2, x2-1,y2-2, c);
497 
498  c = ShadeColor(back_color, 1.6); // full highlight
499  DrawLine(x2-1,y1+1, x2-1,y2, c);
500  DrawLine(x1 ,y2-1, x2,y2-1, c);
501  }
502 
503  // draw frame:
504  if (style & WIN_BLACK_FRAME)
505  DrawRect(x1,y1,x2-1,y2-1, ShadeColor(Color::Black, 1.0));
506  else if (style & WIN_WHITE_FRAME)
507  DrawRect(x1,y1,x2-1,y2-1, ShadeColor(Color::White, 1.0));
508  }
509 }
510 
511 void
513 {
514  if (shown && font && text.length()) {
515  Rect label_rect;
516 
517  if (text_insets.left) {
518  label_rect.w = rect.w;
519  label_rect.h = rect.h;
520 
521  label_rect.Inset(text_insets.left,
525  }
526  else {
527  int border_size = 4;
528 
530  border_size = 8;
531 
532  label_rect.x = border_size;
533  label_rect.y = border_size;
534  label_rect.w = rect.w - border_size * 2;
535  label_rect.h = rect.h - border_size * 2;
536  }
537 
538  font->SetAlpha(alpha);
539 
540  // no tabs set:
541  if (tab[0] == 0) {
542  DWORD text_flags = DT_WORDBREAK | text_align;
543 
544  if (single_line)
545  text_flags = text_flags | DT_SINGLELINE;
546 
547  if (style & WIN_TEXT_SHADOW) {
548  label_rect.x++;
549  label_rect.y++;
550 
551  if (transparent) {
553  DrawText(text.data(), 0, label_rect, text_flags);
554  }
555 
556  else {
557  Color shadow = ShadeColor(back_color, 1.6);
558  font->SetColor(shadow);
559  DrawText(text.data(), 0, label_rect, text_flags);
560  }
561 
562  label_rect.x--;
563  label_rect.y--;
564  }
565 
566  Color fore = ShadeColor(fore_color, 1);
567  font->SetColor(fore);
568  DrawText(text.data(), 0, label_rect, text_flags);
569  }
570 
571  // use tabs:
572  else {
573  }
574 
575  font->SetAlpha(1);
576  }
577 }
578 
579 // +--------------------------------------------------------------------+
580 
581 void
583 {
584  if (n >= 0 && n < 10)
585  tab[n] = x;
586 }
587 
588 int
590 {
591  if (n >= 0 && n < 10)
592  return tab[n];
593 
594  return 0;
595 }
596 
597 // +--------------------------------------------------------------------+
598 
599 void
600 ActiveWindow::SetText(const char* t)
601 {
602  if (t && text != t) {
603  int len = strlen(t);
604 
605  if (len > 0) {
606  char* buf = new(__FILE__,__LINE__) char[2*len];
607 
608  if (buf != 0) {
609  const char* src = t;
610  char* dst = buf;
611 
612  while (*src) {
613  if (*src != '\\') {
614  *dst++ = *src++;
615  }
616  else {
617  src++;
618 
619  switch (*src) {
620  case 'n': *dst++ = '\n'; break;
621  case 't': *dst++ = '\t'; break;
622  default: *dst++ = *src; break;
623  }
624 
625  src++;
626  }
627  }
628 
629  *dst = 0;
630 
631  if (text != buf) {
632  text = buf;
633  }
634 
635  delete [] buf;
636  }
637  }
638  else {
639  text = t;
640  }
641  }
642 }
643 
644 void
646 {
647  if (t && text != t) {
648  int len = t.length();
649 
650  if (len > 0 && t.contains('\\')) {
651  char* buf = new(__FILE__,__LINE__) char[2*len];
652 
653  if (buf != 0) {
654  const char* src = t;
655  char* dst = buf;
656 
657  while (*src) {
658  if (*src != '\\') {
659  *dst++ = *src++;
660  }
661  else {
662  src++;
663 
664  switch (*src) {
665  case 'n': *dst++ = '\n'; break;
666  case 't': *dst++ = '\t'; break;
667  default: *dst++ = *src; break;
668  }
669 
670  src++;
671  }
672  }
673 
674  *dst = 0;
675 
676  if (text != buf) {
677  text = buf;
678  }
679 
680  delete [] buf;
681  }
682  }
683  else {
684  text = t;
685  }
686  }
687 }
688 
689 // +--------------------------------------------------------------------+
690 
691 void
692 ActiveWindow::AddText(const char* t)
693 {
694  if (t) {
695  text += t;
696  }
697 }
698 
699 void
701 {
702  if (t) {
703  text += t;
704  }
705 }
706 
707 void
709 {
710  if (a == DT_LEFT || a == DT_RIGHT || a == DT_CENTER)
711  text_align = a;
712 }
713 
714 void
716 {
717  margins = m;
718  CalcGrid();
719 }
720 
721 void
723 {
724  text_insets = t;
725 }
726 
727 void
729 {
730  cell_insets = c;
731 }
732 
733 void
734 ActiveWindow::SetCells(int cx, int cy, int cw, int ch)
735 {
736  cells.x = cx;
737  cells.y = cy;
738  cells.w = cw;
739  cells.h = ch;
740 
741  if (cells.w < 1)
742  cells.w = 1;
743 
744  if (cells.h < 1)
745  cells.h = 1;
746 }
747 
748 void
750 {
751  if (alpha != a) {
752  alpha = (float) a;
753 
754  Color c = Color::White;
755  c.SetAlpha((BYTE) (alpha*255));
756 
757  if (vset && vset->nverts) {
758  for (int i = 0; i < vset->nverts; i++) {
759  vset->diffuse[i] = c.Value();
760  }
761  }
762  }
763 }
764 
765 // +--------------------------------------------------------------------+
766 
767 void
768 ActiveWindow::DrawText(const char* txt, int count, Rect& txt_rect, DWORD flags)
769 {
770  if (font) {
771  font->SetAlpha(alpha);
772  Window::DrawText(txt, count, txt_rect, flags);
773  }
774 }
775 
776 // +--------------------------------------------------------------------+
777 
778 void
780 {
781  AWMap* map = new(__FILE__,__LINE__) AWMap(eid, client, callback);
782 
783  if (map != 0)
784  clients.append(map);
785 }
786 
787 void
789 {
790  AWMap test(eid, client, 0);
791  int index = clients.index(&test);
792 
793  if (index >= 0)
794  delete clients.removeIndex(index);
795 }
796 
797 void
798 ActiveWindow::ClientEvent(int eid, int x, int y)
799 {
800  event.window = this;
801  event.eid = eid;
802  event.x = x;
803  event.y = y;
804 
805  ListIter<AWMap> map = clients;
806  while (++map) {
807  if (map->eid == eid)
808  map->func(map->client, &event);
809  }
810 }
811 
812 // +--------------------------------------------------------------------+
813 
814 int ActiveWindow::OnMouseEnter(int x, int y)
815 {
817  return 0;
818 }
819 
820 int ActiveWindow::OnMouseExit(int x, int y)
821 {
823  return 0;
824 }
825 
826 int ActiveWindow::OnMouseMove(int x, int y)
827 {
829  return 0;
830 }
831 
833 {
834  ClientEvent(EID_MOUSE_WHEEL, wheel, 0);
835  return 0;
836 }
837 
839 {
841  return 0;
842 }
843 
844 int ActiveWindow::OnLButtonUp(int x, int y)
845 {
847  return 0;
848 }
849 
851 {
853  return 0;
854 }
855 
857 {
859  return 0;
860 }
861 
863 {
865  return 0;
866 }
867 
868 int ActiveWindow::OnRButtonUp(int x, int y)
869 {
871  return 0;
872 }
873 
874 int ActiveWindow::OnKeyDown(int vk, int flags)
875 {
876  ClientEvent(EID_KEY_DOWN, vk, flags);
877  return 0;
878 }
879 
880 int ActiveWindow::OnDragStart(int x, int y)
881 {
883  return 0;
884 }
885 
886 int ActiveWindow::OnDragDrop(int x, int y, ActiveWindow* source)
887 {
888  ClientEvent(EID_DRAG_DROP, x, y);
889  return 0;
890 }
891 
893 {
894  return rect;
895 }
896 
897 // +--------------------------------------------------------------------+
898 
900 {
902  if (dispatch)
903  dispatch->SetFocus(this);
904 
905  focus = true;
907 }
908 
910 {
912  if (dispatch)
913  dispatch->KillFocus(this);
914 
915  focus = false;
917 }
918 
919 // +--------------------------------------------------------------------+
920 
923 {
925  if (dispatch)
926  return (ActiveWindow*) dispatch->GetCapture();
927 
928  return 0;
929 }
930 
931 // +--------------------------------------------------------------------+
932 
933 int
935 {
937  if (dispatch)
938  return dispatch->CaptureMouse(this);
939 
940  return 0;
941 }
942 
943 // +--------------------------------------------------------------------+
944 
945 int
947 {
949  if (dispatch)
950  return dispatch->ReleaseMouse(this);
951 
952  return 0;
953 }
954 
955 // +--------------------------------------------------------------------+
956 
957 bool
959 {
960  if (form)
961  return form->IsTopMost();
962 
963  return true;
964 }
965 
966 // +--------------------------------------------------------------------+
967 
970 {
972  while (++iter) {
973  ActiveWindow* w = iter.value();
974  if (w->GetID() == id)
975  return w;
976 
977  ActiveWindow* w2 = w->FindChild(id);
978 
979  if (w2)
980  return w2;
981  }
982 
983  return 0;
984 }
985 
986 
987 // +--------------------------------------------------------------------+
988 
991 {
992  ActiveWindow* mouse_tgt = 0;
993 
995  while (++iter) {
996  ActiveWindow* test = iter.value();
997  if (test->TargetRect().Contains(x,y))
998  mouse_tgt = test;
999  }
1000 
1001  return mouse_tgt;
1002 }