1 /*
2  * wmslib/src/abut/term.c, part of wmslib (Library functions)
3  * Copyright (C) 1995-1996 William Shubert
4  * See "configure.h.in" for more copyright information.
5  *
6  * Source code for "term" scrolling terminal-like widgety thing.
7  */
8 
9 
10 #include <wms.h>
11 #include <but/but.h>
12 #include <but/plain.h>
13 #include <but/tbin.h>
14 #include <but/slide.h>
15 #include <but/canvas.h>
16 #ifdef  _ABUT_TERM_H_
17   Levelization Error.
18 #endif
19 #include "term.h"
20 
21 
22 /**********************************************************************
23  * Forward declarations
24  **********************************************************************/
25 static ButWinFunc  resize;
26 static void  curOffWin(But *but, int activeLine, int passiveLine,
27 		       int mouseY);
28 
29 
30 /**********************************************************************
31  * Functions
32  **********************************************************************/
abutTerm_create(Abut * abut,ButWin * parent,int layer,bool editable)33 AbutTerm  *abutTerm_create(Abut *abut, ButWin *parent,
34 			   int layer, bool editable)  {
35   AbutTerm  *term;
36 
37   assert(MAGIC(abut));
38   term = wms_malloc(sizeof(AbutTerm));
39   MAGIC_SET(term);
40   term->abut = abut;
41   term->swin = abutSwin_create(term, parent, layer,
42 			       BUT_DRAWABLE|BUT_PRESSABLE, resize);
43   if (editable)
44     term->bg = butPlain_create(term->swin->win, 0, BUT_DRAWABLE,
45 			       BUT_HIBG);
46   else
47     term->bg = butPlain_create(term->swin->win, 0, BUT_DRAWABLE,
48 			       BUT_BG);
49   term->tbin = butTbin_create(term->swin->win, 1,
50 			      BUT_DRAWABLE|BUT_PRESSABLE, "");
51   if (!editable)
52     butTbin_setReadOnly(term->tbin, TRUE);
53   butTbin_setOffWinCallback(term->tbin, curOffWin);
54   term->state = abutTermState_steady;
55   return(term);
56 }
57 
58 
abutTerm_destroy(AbutTerm * term)59 void  abutTerm_destroy(AbutTerm *term)  {
60   assert(MAGIC(term));
61   MAGIC_UNSET(term);
62 }
63 
64 
abutTerm_set(AbutTerm * term,const char * text)65 void  abutTerm_set(AbutTerm *term, const char *text)  {
66   ButEnv  *env;
67 
68   assert(MAGIC(term));
69   env = term->abut->env;
70   butTbin_set(term->tbin, text);
71   butCan_resizeWin(term->swin->win, 0, butTbin_numLines(term->tbin) *
72 		   butEnv_fontH(env, 0) + butEnv_stdBw(env) * 2, TRUE);
73 }
74 
75 
abutTerm_resize(AbutTerm * term,int x,int y,int w,int h)76 void  abutTerm_resize(AbutTerm *term, int x, int y, int w, int h)  {
77   int  fontH = butEnv_fontH(term->abut->env, 0);
78   int  bw = butEnv_stdBw(term->abut->env);
79 
80   assert(MAGIC(term));
81   abutSwin_resize(term->swin, x, y, w, h, (fontH * 3) / 2, fontH);
82   butCan_resizeWin(term->swin->win, 0, butTbin_numLines(term->tbin) * fontH +
83 		   bw * 2, TRUE);
84 }
85 
86 
resize(ButWin * win)87 static ButOut  resize(ButWin *win)  {
88   AbutSwin  *swin = butWin_packet(win);
89   AbutTerm  *term = swin->packet;
90   char  *temp;
91   int  w, h, len;
92   int  bw;
93 
94   assert(MAGIC(swin));
95   assert(MAGIC(term));
96   w = butWin_w(win);
97   h = butWin_h(win);
98   but_resize(term->bg, 0,0, w,h);
99   bw = butEnv_stdBw(term->abut->env);
100   if (but_w(term->tbin) == w)  {
101     but_resize(term->tbin, 0,bw, w,h - bw);
102   } else  {
103     /*
104      * This is a mega-cheesy kludge to work around the non-resizability of
105      *   a tbin widget.  Basically I cut the whole terminal script, clear it,
106      *   resize the tbin, then paste it all back in.  Ugh.
107      */
108     len = butTbin_len(term->tbin);
109     temp = wms_malloc(len + 1);
110     memcpy(temp, butTbin_get(term->tbin), len);
111     temp[len] = '\0';
112     butTbin_set(term->tbin, "");
113     but_resize(term->tbin, 0,bw, w,h - bw);
114     butTbin_set(term->tbin, temp);
115     wms_free(temp);
116   }
117   return(0);
118 }
119 
120 
curOffWin(But * but,int activeLine,int passiveLine,int mouseY)121 static void  curOffWin(But *but, int activeLine, int passiveLine,
122 		       int mouseY)  {
123   ButWin  *win = but_win(but);
124   ButEnv  *env = butWin_env(win);
125   AbutSwin  *swin = butWin_packet(win);
126   AbutTerm  *term;
127   int  y, h, bw = butEnv_stdBw(env);
128   int  lines;
129   AbutTermState  newState;
130 
131   assert(MAGIC(swin));
132   term = swin->packet;
133   assert(MAGIC(term));
134   newState = abutTermState_steady;
135   h = butEnv_fontH(env, 0);
136   y = activeLine * h + bw;
137   if (passiveLine != activeLine)  {
138     if (y <= butCan_yOff(win) + bw)  {
139       if (mouseY < butCan_yOff(win) - h)
140 	newState = abutTermState_fastUp;
141       else if (mouseY < butCan_yOff(win))
142 	newState = abutTermState_slowUp;
143     } else if (y + h + bw >= butCan_yOff(win) + butWin_viewH(win))  {
144       if (mouseY > butCan_yOff(win) + butWin_viewH(win) + h)
145 	newState = abutTermState_fastDown;
146       else if (mouseY > butCan_yOff(win) + butWin_viewH(win))
147 	newState = abutTermState_slowDown;
148     }
149   }
150   if (newState != term->state)  {
151     term->state = newState;
152     switch(newState)  {
153     case abutTermState_fastUp:
154       butSlide_startSlide(swin->vSlide, FALSE, -h*10, FALSE);
155       break;
156     case abutTermState_slowUp:
157       butSlide_startSlide(swin->vSlide, FALSE, -h, FALSE);
158       break;
159     case abutTermState_steady:
160       butSlide_stopSlide(swin->vSlide);
161       break;
162     case abutTermState_slowDown:
163       butSlide_startSlide(swin->vSlide, FALSE, h, FALSE);
164       break;
165     case abutTermState_fastDown:
166       butSlide_startSlide(swin->vSlide, FALSE, h*10, FALSE);
167       break;
168     }
169   }
170   if (passiveLine == activeLine)  {
171     lines = butTbin_numLines(but);
172     if (activeLine >= lines)
173       lines = activeLine + 1;
174     if (lines * h + bw * 2 > butWin_h(win))  {
175       butCan_resizeWin(swin->win, 0, lines * h + bw * 2, TRUE);
176     }
177     if (y < butCan_yOff(win))  {
178       y -= bw;
179       butCan_slide(win, BUT_NOCHANGE, y, TRUE);
180     } else if (y + h > butCan_yOff(win) + butWin_viewH(win))  {
181       y = y + h + bw - butWin_viewH(win);
182       butCan_slide(win, BUT_NOCHANGE, y, TRUE);
183     }
184   }
185 }
186