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